[英]postgreSQL optimisation
我正在研究一個大的PostgreSQL項目,不幸的是在生產中(在一個包含90列的表中有3百萬條記錄)在大約2分鍾內運行查詢(具有2個條件的select / join)。
假設我的查詢沒有什么可以優化的,我可以修改任何設置以使其運行得更快嗎? 這是數據庫的配置,我不知道什么適合我的需求:
version PostgreSQL 8.4.4 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44), 32-bit
checkpoint_completion_target 0.9
checkpoint_segments 10
custom_variable_classes pg_stat_statements
effective_cache_size 1GB
lc_collate fr_FR.UTF-8
lc_ctype fr_FR.UTF-8
listen_addresses *
log_autovacuum_min_duration 0
log_line_prefix %t [%p]: [%l-1] user=%u,db=%d
log_min_duration_statement 30s
logging_collector on
maintenance_work_mem 128MB
max_connections 100
max_stack_depth 2MB
pg_stat_statements.max 1000
pg_stat_statements.save on
pg_stat_statements.track all
random_page_cost 1.5
server_encoding UTF8
shared_buffers 128MB
TimeZone Europe/Paris
track_functions pl
wal_buffers 1MB
work_mem 8MB
查詢:
SELECT distinct
((Table_Commande_Historique.COD_STECIAL
|| ',' || Table_Commande_Historique.COD_MCIAL
|| ',' || Table_Commande_Historique.NUM_REC_CLI
|| ',' || Table_Commande_Historique.NUM_DNT_CLI
|| ',' || Table_Commande_Historique.NUM_DDE)) cle
FROM G1DDE2_DDE Table_Commande_Historique
inner join "K2VER2_VER" ver
on ( Table_Commande_Historique.NUM_REC_CLI
= (string_to_array(ver.num_cle,','))[3]::int
OR Table_Commande_Historique.NUM_DNT_CLI
= (string_to_array(ver.num_cle,','))[3]::int
OR ver.num_cle = (Table_Commande_Historique.COD_MCIAL
|| ',' || Table_Commande_Historique.NUM_REC_CLI)
OR ver.num_cle = (Table_Commande_Historique.COD_MCIAL
|| ',' || Table_Commande_Historique.NUM_DNT_CLI) );
索引:
CREATE INDEX idx_combo1
ON g1dde2_dde
USING btree
(((cod_mcial || ','::text) || num_rec_cli) );
CREATE INDEX idx_combo2
ON g1dde2_dde
USING btree
(((cod_mcial || ','::text) || num_dnt_cli) );
CREATE INDEX idx_dnt
ON g1dde2_dde
USING btree
(num_dnt_cli );
CREATE INDEX idx_rec
ON g1dde2_dde
USING btree
(num_rec_cli );
CREATE INDEX idx_k2ver3sb
ON "K2VER2_VER"
USING btree
(num_cle );
說明:
"HashAggregate (cost=197.97..201.77 rows=69 width=29)"
" -> Nested Loop (cost=1.29..197.35 rows=248 width=29)"
" -> Seq Scan on "K2VER2_VER" ver (cost=0.00..2.58 rows=58 width=19)"
" -> Bitmap Heap Scan on g1dde2_dde table_commande_historique (cost=1.29..2.84 rows=5 width=29)"
" Recheck Cond: ((table_commande_historique.num_rec_cli = ((string_to_array((ver.num_cle)::text, ','::text))[3])::integer) OR (table_commande_historique.num_dnt_cli = ((string_to_array((ver.num_cle)::text, ','::text))[3])::integer) OR ((ver.num_cle)::text = (((table_commande_historique.cod_mcial)::text || ','::text) || (table_commande_historique.num_rec_cli)::text)) OR ((ver.num_cle)::text = (((table_commande_historique.cod_mcial)::text || ','::text) || (table_commande_historique.num_dnt_cli)::text)))"
" -> BitmapOr (cost=1.29..1.29 rows=5 width=0)"
" -> Bitmap Index Scan on idx_rec (cost=0.00..0.32 rows=2 width=0)"
" Index Cond: (table_commande_historique.num_rec_cli = ((string_to_array((ver.num_cle)::text, ','::text))[3])::integer)"
" -> Bitmap Index Scan on idx_dnt (cost=0.00..0.32 rows=1 width=0)"
" Index Cond: (table_commande_historique.num_dnt_cli = ((string_to_array((ver.num_cle)::text, ','::text))[3])::integer)"
" -> Bitmap Index Scan on idx_combo1 (cost=0.00..0.32 rows=1 width=0)"
" Index Cond: ((ver.num_cle)::text = (((table_commande_historique.cod_mcial)::text || ','::text) || (table_commande_historique.num_rec_cli)::text))"
" -> Bitmap Index Scan on idx_combo2 (cost=0.00..0.32 rows=1 width=0)"
" Index Cond: ((ver.num_cle)::text = (((table_commande_historique.cod_mcial)::text || ','::text) || (table_commande_historique.num_dnt_cli)::text))"
version PostgreSQL 8.4.4
那是個問題。 請閱讀此內容並考慮使用次要版本來修復安全漏洞和錯誤:
http://www.postgresql.org/support/versioning/
這些有時會包含引入性能問題的錯誤。 要查看您將獲得的修復,您可以在此處查看8.4.5至8.4.11注釋:
http://www.postgresql.org/docs/8.4/static/release.html
一些基於RAM的設置可能太低,但不知道系統上有多少RAM以及其他運行的內容,沒有辦法建議具體的數字。
shared_buffers 128MB
Linux上專用數據庫服務器的通常建議是將其設置為系統總RAM的25%,最大可能為8GB,並根據基准測試從那里進行調整。
effective_cache_size 1GB
這不會分配任何RAM,但允許計划程序根據對同一查詢中較早讀取的高速緩存仍然存在的可能性的估計來花費重復讀取文件的成本。 我建議你將你的shared_buffers大小添加到操作系統顯示為緩存的大小。
work_mem 8MB
這個很棘手。 它可以通過多種方式幫助查詢性能,但是高值往往會將事物從緩存中推出,從而增加磁盤訪問。 您還需要考慮每個查詢可以多次分配這么多空間(針對不同的查詢步驟),因此您通常應允許每個連接允許一次分配此大小。 這是它往往是有益使用連接池漏斗大量用戶的原因之一到實際的數據庫連接的數量有限。 如果您能夠承受更大的尺寸,則很可能有助於此查詢,因為它可能會使位圖索引掃描變得“有損”並需要重新檢查索引條件。
你沒有設置cpu_tuple_cost
,但我發現默認設置通常太低而無法提供最佳的整體計划。 鑒於你的大表有90列,我建議將其從0.01增加到0.05。
您沒有設置effective_io_concurrency
,但這可能會有所幫助。 我會測試不同的值。 (當然,在運行測試來比較替代方案的性能時,請注意緩存問題。)
maintenance_work_mem 128MB
根據您擁有多少RAM,這可能是合理的,也可能是不合理的。 它不會影響您的直接問題,但增加它可能有助於autovacuum更有效地運行,並將幫助索引構建更快地運行。
這些可能有點低:
checkpoint_segments 10
wal_buffers 1MB
它們不是您當前問題的一部分,但它們有時會導致額外的磁盤寫入,因此調整它們可能會付出代價。 除非您的計算機內存非常有限,否則wal_buffers
通常應為32MB。 checkpoint_segments
很難在不知道更多的情況下進行估算,但如果您檢查日志和統計信息並發現檢查點發生得太頻繁,您可能希望增加此值,直到檢查點基於checkpoint_timeout
發生。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.