乾貨 | 基於KingbaseES的SQL性能調優(附案例)


隨着互聯網技術在商業應用中的普遍普及,數據庫應用日益龐大複雜,隨之數據庫性能表現的重要性也愈加凸顯。在數據庫的衆多性能問題中,SQL性能問題佔有極大的比例,所以,SQL性能調優也就成爲了數據庫管理員進階須要掌握的一項重要技能。憑藉着金倉的多年來的海量應用數據,咱們總結出了一些SQL性能調優經驗供讀者使用。
web


常見問題分析算法

SQL性能問題通常表如今過長的響應時間,當時間長到應用沒法忍受時,就會成爲一個咱們須要解決的性能問題。結合衆多現場的狀況,能夠得出如下常見問題緣由:數據庫


一、缺乏SQL訪問結構安全

缺乏索引、物化視圖、分區之類的SQL訪問結構是致使SQL性能欠佳的典型緣由。例如:微信

  • 選擇率較低的查詢謂詞在大表上使用全表掃描,而沒有索引網絡

  • 排序、max/min等狀況沒有選用索引架構



TEST=# explain analyze select max(id) from t1;
oop

                                                    QUERY PLAN性能

-------------------------------------------------------------------------------------------------------------------flex

 Aggregate  (cost=17906.00..17906.01 rows=1 width=4) (actual time=180.486..180.486 rows=1 loops=1)

   ->  Seq Scan on T1  (cost=0.00..15406.00 rows=1000000 width=4) (actual time=0.014..89.855 rows=1000000 loops=1)

 Planning time: 0.157 ms

Execution time: 180.531 ms


示例1-問題(解決方法見下文)




二、次優的執行計劃

優化器在大部分時候都能給出較優的執行計劃。可是,有時候,由於優化器自身的侷限性,有可能選擇不理想的計劃。例如:

  • 多表查詢的鏈接順序未能將能夠過濾更多數據的兩錶鏈接最早執行

  • 鏈接算法不夠好

  • 選擇率的估算不許確


TEST=# explain analyze select * from t3,t1 where t3.c1 = t3.c2 and t3.c2 = t3.c3 and  t1.id = t3.c1;

                                                        QUERY PLAN

---------------------------------------------------------------------------------------------------------------------------

 Nested Loop  (cost=0.42..20617.31 rows=25 width=23) (actual time=0.029..1676.549 rows=1000000 loops=1)

   ->  Seq Scan on T3  (cost=0.00..20406.00 rows=25 width=12) (actual time=0.019..171.783 rows=1000000 loops=1)

         Filter: ((C1 = C2) AND (C2 = C3))

   ->  Index Scan using T1_ID_IDX on T1  (cost=0.42..8.44 rows=1 width=11) (actual time=0.001..0.001 rows=1 loops=1000000)

         Index Cond: (ID = T3.C1)

 Planning time: 0.819 ms

Execution time: 1705.336 ms

(7 rows)


示例2-問題(解決方法見下文)


三、陳舊的統計信息

當統計信息維護操做(自動或手動)沒法跟上DML致使的表數據更改時,收集到的統計信息可能會過期。因爲表上的陳舊統計信息沒法準確反映表數據,所以優化器能夠基於錯誤信息作出決策並生成次優執行計劃。


TEST=# explain analyze select * from student where sno > 2;

                                                      QUERY PLAN

-----------------------------------------------------------------------------------------------------------------------

 Bitmap Heap Scan on STUDENT  (cost=60.12..156.12 rows=2560 width=40) (actual time=1.381..3.588 rows=9998 loops=1)

   Recheck Cond: (SNO > 2)

   Heap Blocks: exact=64

   ->  Bitmap Index Scan on IDX_STU  (cost=0.00..59.48 rows=2560 width=0) (actual time=1.339..1.339 rows=9998 loops=1)

         Index Cond: (SNO > 2)

 Planning time: 0.096 ms

 Execution time: 4.254 ms

(7 rows)


TEST=# analyze student;

ANALYZE

TEST=# explain analyze select * from student where sno > 2;

                                                QUERY PLAN

----------------------------------------------------------------------------------------------------------

 Seq Scan on STUDENT  (cost=0.00..189.00 rows=9999 width=19) (actual time=0.015..2.362 rows=9998 loops=1)

   Filter: (SNO > 2)

   Rows Removed by Filter: 2

 Planning time: 0.215 ms

 Execution time: 3.050 ms

(5 rows)


示例3-問題


四、低效的SQL語句設計

若是SQL語句執行了一些沒必要要的工做,那麼優化器將沒法作不少事情來提升其性能。低效設計的例子包括:

  • 忽略添加鏈接條件,致使笛卡爾積鏈接

  • 過濾條件沒有下推

  • 指定UNION而不是UNION ALL

  • 使用OR而不是UNION


TEST=# explain analyze select * from or_union o,or_union1 o1 where o.b=o1.b and (o.a=1 or o1.a=10 );

                                        QUERY PLAN                                                           

-----------------------------------------------------------------------------------------

 Hash Join  (cost=15417.00..37867.00 rows=50200 width=16) (actual time=354.603..1325.621 rows=50000 loops=1)

   Hash Cond: (O.B = O1.B)

   Join Filter: ((O.A = 1) OR (O1.A = 10))

   Rows Removed by Join Filter: 450000

   ->  Seq Scan on OR_UNION O  (cost=0.00..7213.00 rows=500000 width=8) (actual time=0.018..133.690 rows=500000 loops=1)

   ->  Hash  (cost=7213.00..7213.00 rows=500000 width=8) (actual time=351.181..351.181 rows=500000 loops=1)

         Buckets: 131072  Batches: 8  Memory Usage: 3465kB

         ->  Seq Scan on OR_UNION1 O1  (cost=0.00..7213.00 rows=500000 width=8) (actual time=0.018..135.804 rows=500000 loops=1)

 Planning time: 0.587 ms

 Execution time: 1330.277 ms


示例4-問題(解決方法見下文)


五、硬件或架構問題

受限於當前硬件環境(CPU、內存、IO、網絡等)、架構,全部的優化手段都不足以達到預期性能,則須要作硬件或者架構擴展。


優化手段

爲了應對SQL性能問題,KingbaseES在不斷升級優化器的同時也提供了諸多優化手段,常規優化手段以下。


一、索引

索引是一種有序的存儲結構,也是一項極爲重要的SQL優化手段,能夠提升數據檢索的速度。經過在表中的一個或多個列上建立索引,不少SQL語句的執行效率能夠獲得極大的提升。kingbase提供的索引類型包括BRTEE、HASH、GIST、GIN、BRIN、BLOOM、TRGM。


TEST=# create index on t1(id);

CREATE INDEX

TEST=# explain analyze select max(id) from t1;

                                                                     QUERY PLAN

----------------------------------------------------------------------------------------------------------------------------------------------------

 Result  (cost=0.46..0.47 rows=1 width=4) (actual time=0.069..0.070 rows=1 loops=1)

   InitPlan 1 (returns $0)

     ->  Limit  (cost=0.42..0.46 rows=1 width=4) (actual time=0.064..0.065 rows=1 loops=1)

           ->  Index Only Scan Backward using T1_ID_IDX on T1  (cost=0.42..33889.43 rows=1000000 width=4) (actual time=0.063..0.063 rows=1 loops=1)

                 Index Cond: (ID IS NOT NULL)

                 Heap Fetches: 1

 Planning time: 0.283 ms

Execution time: 0.104 ms

(8 rows)


示例1-解決方法(問題描述見上文)


二、使用HINT

查詢優化器在儘可能提供最優的執行計劃,可是由於種種緣由,優化器以及它所依賴的統計信息存在着一些侷限性。因此,某些狀況下,優化器提供的統計信息不是最優,須要人工干預。HINT則是爲了解決該問題而提供的一項功能,能夠幫助用戶人爲的控制執行計劃。HINT目前可控制的內容包括:掃描類型、鏈接類型、鏈接順序、JOIN返回行數、GUC參數等。


TEST=# /*+HashJoin(T1 T3)*/explain analyze select * from t3,t1 where t3.c1 = t3.c2 and t3.c2 = t3.c3 and  t1.id = t3.c1;

                                                      QUERY PLAN

----------------------------------------------------------------------------------------------------------------------

 Hash Join  (cost=20406.31..39562.56 rows=25 width=23) (actual time=323.815..699.533 rows=1000000 loops=1)

   Hash Cond: (T1.ID = T3.C1)

   ->  Seq Scan on T1  (cost=0.00..15406.00 rows=1000000 width=11) (actual time=0.016..67.093 rows=1000000 loops=1)

   ->  Hash  (cost=20406.00..20406.00 rows=25 width=12) (actual time=323.720..323.720 rows=1000000 loops=1)

         Buckets: 1048576 (originally 1024)  Batches: 1 (originally 1)  Memory Usage: 51161kB

         ->  Seq Scan on T3  (cost=0.00..20406.00 rows=25 width=12) (actual time=0.017..188.784 rows=1000000 loops=1)

               Filter: ((C1 = C2) AND (C2 = C3))

 Planning time: 0.399 ms

 Execution time: 730.199 ms

(9 rows)


示例2-解決方法(問題描述見上文)


三、使用並行

KingbaseES能設計出利用多 CPU 讓查詢更快的查詢計劃。這種特性被稱爲並行查詢。對於分析型語句,並行查詢帶來的速度提高是顯著的。不少查詢在使用並行查詢時查詢速度比以前快了超過兩倍,有些查詢是之前的四倍甚至更多的倍數。那些訪問大量數據但只返回其中少數行給用戶的查詢最能從並行查詢中獲益。


TEST=# explain analyze select avg(id) from t2;

                                                      QUERY PLAN

-----------------------------------------------------------------------------------------------------------------------

 Aggregate  (cost=208335.00..208335.01 rows=1 width=32) (actual time=1572.051..1572.051 rows=1 loops=1)

   ->  Seq Scan on T2  (cost=0.00..183334.80 rows=10000080 width=4) (actual time=0.021..892.509 rows=10000000 loops=1)

 Planning time: 0.132 ms

Execution time: 1572.108 ms

(4 rows)

TEST=# set max_parallel_workers_per_gather to 8;

SET

TEST=# explain analyze select avg(id) from t2;

                                                                QUERY PLAN

------------------------------------------------------------------------------------------------------------------------------------------

 Finalize Aggregate  (cost=109334.72..109334.73 rows=1 width=32) (actual time=391.702..391.703 rows=1 loops=1)

   ->  Gather  (cost=109334.20..109334.71 rows=5 width=32) (actual time=391.588..407.580 rows=6 loops=1)

Workers Planned: 5

         Workers Launched: 5

         ->  Partial Aggregate  (cost=108334.20..108334.21 rows=1 width=32) (actual time=383.329..383.330 rows=1 loops=6)

               ->  Parallel Seq Scan on T2  (cost=0.00..103334.16 rows=2000016 width=4) (actual time=0.028..250.937 rows=1666667 loops=6)

 Planning time: 0.115 ms

 Execution time: 407.654 ms

(8 rows)


示例3-解決方法


四、調整性能參數

KingbaseES容許對單個查詢關閉特定的優化器特性。若是優化器爲特定查詢選擇的執行計劃並非最優的,能夠經過設置這些參數強制優化器選擇一個更好的執行計劃來臨時解決這個問題。常見修改參數包括:

  • 節點開關參數,如enable_seqscan

  • 內存參數,如work_mem


五、改寫SQL語句

數據庫的使用者在書寫SQL語句的時候也常常會考慮到查詢的性能,可是一個應用程序可能要寫大量的SQL語句,並且有些SQL語句的邏輯極爲複雜,數據庫應用開發人員很難面面俱到地寫出性能良好的語句。當須要改寫SQL語句時能夠考慮如下方式:

  • 條件儘可能下推

  • 子查詢轉爲join

  • UNION轉爲UNION ALL

  • 將OR改寫爲UNION


特別須要注意的是,SQL語句改寫須要考慮語義等價的問題。


explain analyze select * from or_union o,or_union1 o1 where o.a=1 and o.b=o1.b

union

select * from or_union o,or_union1 o1 where o1.a=10 and o.b=o1.b

;

                                      QUERY PLAN                                                                        

-----------------------------------------------------------------------------------------

 HashAggregate  (cost=24099.91..24601.92 rows=50201 width=16) (actual time=435.391..462.814 rows=50000 loops=1)

   Group Key: O.A, O.B, O1.A, O1.B

   ->  Append  (cost=4409.47..23597.90 rows=50201 width=16) (actual time=63.081..387.360 rows=50000 loops=1)

         ->  Hash Join  (cost=4409.47..13999.47 rows=50200 width=16) (actual time=63.081..380.380 rows=50000 loops=1)

               Hash Cond: (O1.B = O.B)

               ->  Seq Scan on OR_UNION1 O1  (cost=0.00..7213.00 rows=500000 width=8) (actual time=0.022..107.463 rows=500000 loops=1)

               ->  Hash  (cost=3781.97..3781.97 rows=50200 width=8) (actual time=62.946..62.946 rows=50000 loops=1)

                     Buckets: 65536  Batches: 1  Memory Usage: 2466kB

                     ->  Bitmap Heap Scan on OR_UNION O  (cost=941.47..3781.97 rows=50200 width=8) (actual time=13.723..41.791 rows=50000 loops=1)

                           Recheck Cond: (A = 1)

                           Heap Blocks: exact=2213

                           ->  Bitmap Index Scan on OR_UNION_A_IDX  (cost=0.00..928.92 rows=50200 width=0) (actual time=13.097..13.097 rows=50000 loops=1)

                                 Index Cond: (A = 1)

         ->  Hash Join  (cost=8.41..9096.42 rows=1 width=16) (actual time=0.169..0.169 rows=0 loops=1)

               Hash Cond: (O_1.B = O1_1.B)

               ->  Seq Scan on OR_UNION O_1  (cost=0.00..7213.00 rows=500000 width=8) (actual time=0.024..0.024 rows=1 loops=1)

               ->  Hash  (cost=8.40..8.40 rows=1 width=8) (actual time=0.106..0.106 rows=0 loops=1)

                     Buckets: 1024  Batches: 1  Memory Usage: 8kB

                     ->  Index Scan using OR_UNION1_A_IDX on OR_UNION1 O1_1  (cost=0.42..8.40 rows=1 width=8) (actual time=0.106..0.106 rows=0 loops=1)

                           Index Cond: (A = 10)

 Planning time: 0.442 ms

 Execution time: 469.056 ms


示例4-解決方法(問題描述見上文)


以上總結基於金倉核心產品KES在20餘個關鍵行業的關鍵核心系統10多年服務經驗及海量應用數據。做爲國產數據庫領軍企業,人大金倉始終堅持技術創新、產品升級、生態融合,秉承「更可靠、更安全、更智能、更融合」的發展理念,不斷追求卓越產品性能與超一流服務體驗,始終把好數據安全關口,積極夯實數據要素市場基石,助力國家新基建建設。



往期推薦

01

戰略簽約,人大金倉攜手同聯公司簽署戰略協議共同開創信息化創新發展新篇章!

► 點擊閱讀

02

共建產業生態,神州數碼數據庫專題培訓

► 點擊閱讀

03

人大金倉成功中標中國移動自主可控OLTP數據庫聯合創新項目

► 點擊閱讀

你的好友金小倉拍了拍你

並請你幫ta「一鍵三連」

本文分享自微信公衆號 - 金倉數據庫(china-data)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索