Tối ưu hóa truy vấn PostgreSQL 17: Kế hoạch thực thi, điều chỉnh bộ nhớ & EXPLAIN ANALYZE

Mục lục bài viết(13 mục)
PostgreSQL 17 mang đến những cải tiến đáng kể cho bộ tối ưu hóa truy vấn và công cụ thực thi, đòi hỏi một cách tiếp cận tinh tế hơn để điều chỉnh hiệu suất. Hướng dẫn này đi sâu vào việc giải mã các kế hoạch thực thi, tận dụng các tính năng quản lý bộ nhớ mới và tối ưu hóa các mẫu truy vấn phức tạp để đạt được hiệu suất cao nhất.
Hiểu rõ đầu ra EXPLAIN ANALYZE
Nền tảng của việc tối ưu hóa truy vấn PostgreSQL nằm ở việc diễn giải đầu ra EXPLAIN ANALYZE. Lệnh này cung cấp kế hoạch thực thi ước tính của trình lập kế hoạch và số liệu thống kê thời gian chạy thực tế.
Giải mã cây kế hoạch
Mỗi nút trong cây EXPLAIN đại diện cho một thao tác. Các số liệu chính bao gồm:
cost: Chi phí ước tính của trình lập kế hoạch (khởi động..tổng cộng).rows: Số hàng ước tính của trình lập kế hoạch.actual time: Thời gian thực tế đã dành (khởi động..tổng cộng) tính bằng mili giây.actual rows: Số hàng thực tế được trả về.loops: Số lần nút được thực thi.Buffers: Chi tiết về quyền truy cập khối dùng chung, cục bộ và tạm thời (yêu cầu tùy chọnBUFFERS).Wal: Thống kê tạo bản ghi WAL (yêu cầu tùy chọnWAL).Settings: Các tham số GUC ảnh hưởng đến kế hoạch (yêu cầu tùy chọnSETTINGS).
Xem xét một truy vấn đơn giản:
EXPLAIN (ANALYZE, BUFFERS, SETTINGS, WAL)
SELECT p.product_name, c.category_name
FROM products p
JOIN categories c ON p.category_id = c.category_id
WHERE p.price > 100 AND c.category_name = 'Electronics';
Một đầu ra điển hình có thể trông như thế này:
QUERY PLAN
--------------------------------------------------------------------------------------
Hash Join (cost=25.80..50.35 rows=10 width=64) (actual time=0.150..0.250 rows=5 loops=1)
Hash Cond: (p.category_id = c.category_id)
Buffers: shared hit=10 read=2
Wal: records=0, full_page_writes=0, bytes=0
-> Seq Scan on products p (cost=0.00..24.50 rows=20 width=36) (actual time=0.010..0.100 rows=15 loops=1)
Filter: (price > 100::numeric)
Rows Removed by Filter: 85
Buffers: shared hit=5 read=1
-> Hash (cost=25.75..25.75 rows=1 width=32) (actual time=0.030..0.030 rows=1 loops=1)
Buffers: shared hit=5 read=1
-> Seq Scan on categories c (cost=0.00..25.75 rows=1 width=32) (actual time=0.010..0.020 rows=1 loops=1)
Filter: (category_name = 'Electronics'::text)
Rows Removed by Filter: 99
Buffers: shared hit=5 read=1
Planning Time: 0.100 ms
Execution Time: 0.300 ms
Giải thích:
Hash Join: Thao tác cấp cao nhất. Mất0.250 msđể hoàn thành và trả về5hàng. Trình lập kế hoạch ước tính10hàng.Seq Scan on products p: Đã quét bảngproducts. Đã lọc85hàng, giữ lại15. Quét này đã truy cập5khối dùng chung và đọc1từ đĩa.Hash: Đã xây dựng một bảng băm từ quá trình quét bảngcategories.Seq Scan on categories c: Đã quétcategories, đã lọc99hàng, giữ lại1. Quét này cũng đã truy cập5khối dùng chung và đọc1từ đĩa.
Phần Buffers rất quan trọng. shared hit cho biết dữ liệu được tìm thấy trong bộ đệm dùng chung (bộ nhớ), read có nghĩa là dữ liệu phải được tìm nạp từ đĩa. Số lượng read cao thường chỉ ra các chỉ mục bị thiếu hoặc shared_buffers không đủ.
Lỗi ước tính hàng của trình lập kế hoạch
Sự khác biệt giữa rows (ước tính) và actual rows là những dấu hiệu đáng báo động. Sự không khớp đáng kể cho thấy trình lập kế hoạch đã đưa ra một quyết định kém, thường là do:
- Thống kê cũ: Chạy
ANALYZEhoặcVACUUM ANALYZEthường xuyên. - Vị ngữ phức tạp: Trình lập kế hoạch gặp khó khăn với các mệnh đề
WHEREphức tạp, đặc biệt là liên quan đến các hàm hoặc biểu thức. - Độ lệch dữ liệu: Phân phối dữ liệu không đồng nhất có thể đánh lừa trình lập kế hoạch.
ANALYZEvớidefault_statistics_targettăng lên có thể giúp ích. - Thiếu thống kê: Đối với các kiểu dữ liệu tùy chỉnh hoặc biểu thức phức tạp,
CREATE STATISTICScó thể cung cấp thống kê phụ thuộc chức năng hoặc đa cột.
Ví dụ về một lỗi:
Nếu actual rows cho Seq Scan on products p là 10000 nhưng rows là 20, trình lập kế hoạch có thể đã chọn Nested Loop thay vì Hash Join hoặc Merge Join, dẫn đến hiệu suất kém.
Điều chỉnh bộ nhớ: work_mem và maintenance_work_mem
PostgreSQL 17 tiếp tục tinh chỉnh quản lý bộ nhớ. Việc điều chỉnh đúng work_mem và maintenance_work_mem là rất quan trọng.
work_mem
Tham số này xác định lượng bộ nhớ tối đa được sử dụng bởi một thao tác truy vấn (ví dụ: sắp xếp, bảng băm) trước khi ghi dữ liệu tạm thời vào đĩa. Mỗi thao tác như vậy có thể sử dụng lượng này.
- Quá thấp: Dẫn đến I/O đĩa quá mức cho các thao tác sắp xếp và băm, hiển thị dưới dạng
spillhoặcdisktrong đầu raEXPLAIN ANALYZE(ví dụ:Sort Method: external merge Disk: 12345kB). - Quá cao: Có thể dẫn đến lỗi hết bộ nhớ nếu nhiều truy vấn phức tạp chạy đồng thời.
Chiến lược điều chỉnh:
- Xác định tràn: Tìm
Sort Method: external merge DiskhoặcHashAggregate (actual time=... loops=1) Memory: 12345kB, Disk: 67890kBtrongEXPLAIN ANALYZE. - Tăng dần: Bắt đầu với một giá trị thận trọng (ví dụ:
4MBhoặc8MB). Nếu xảy ra tràn, hãy tăng nó. Một giá trị sản xuất phổ biến có thể là64MBđến256MBmỗi phiên, nhưng điều này phụ thuộc rất nhiều vào khối lượng công việc và RAM khả dụng. - Ghi đè cấp phiên: Đối với các truy vấn phức tạp cụ thể,
SET work_mem TO '256MB';có thể được sử dụng.
-- Example: Observe a sort spill
-- Assume 'large_table' has millions of rows and 'some_column' is not indexed
SET work_mem TO '64kB'; -- Artificially low for demonstration
EXPLAIN (ANALYZE, BUFFERS)
SELECT *
FROM large_table
ORDER BY some_column;
-- Output might show:
-- Sort (cost=... rows=... width=...) (actual time=... rows=... loops=1)
-- Sort Key: some_column
-- Sort Method: external merge Disk: 12345kB <-- This indicates a spill
-- Buffers: ...
-- Increase work_mem to prevent spill
SET work_mem TO '256MB'; -- Adjust based on actual spill size and available RAM
EXPLAIN (ANALYZE, BUFFERS)
SELECT *
FROM large_table
ORDER BY some_column;
-- Output should ideally show:
-- Sort (cost=... rows=... width=...) (actual time=... rows=... loops=1)
-- Sort Key: some_column
-- Sort Method: quicksort Memory: 12345kB <-- In-memory sort
-- Buffers: ...
maintenance_work_mem
Được sử dụng cho các thao tác bảo trì như VACUUM, CREATE INDEX, ALTER TABLE ADD FOREIGN KEY. Các thao tác này thường ít thường xuyên hơn nhưng có thể rất tốn bộ nhớ.
- Quá thấp: Làm chậm việc tạo chỉ mục và dọn dẹp, đặc biệt trên các bảng lớn.
- Quá cao: Có thể tiêu thụ bộ nhớ đáng kể trong quá trình bảo trì, có khả năng ảnh hưởng đến các truy vấn đang hoạt động.
Chiến lược điều chỉnh:
- Đặt giá trị này cao hơn
work_mem. Các giá trị phổ biến dao động từ256MBđến1GBtrở lên, tùy thuộc vào kích thước của các bảng lớn nhất của bạn và RAM khả dụng. - Bộ nhớ này được cấp phát cho mỗi thao tác bảo trì, không phải mỗi phiên.
-- Example: Creating an index on a large table
-- A low maintenance_work_mem can make this very slow.
SET maintenance_work_mem TO '16MB'; -- Artificially low
CREATE INDEX idx_large_table_col ON large_table (another_column);
-- This might take a very long time and use temp files.
-- Increase for faster index creation
SET maintenance_work_mem TO '1GB'; -- Or higher, depending on table size
CREATE INDEX idx_large_table_col_new ON large_table (yet_another_column);
-- This should be significantly faster.
Tối ưu hóa sắp xếp tăng dần và kết nối băm
PostgreSQL 17 tăng cường khả năng của trình lập kế hoạch trong việc sử dụng sắp xếp tăng dần và cải thiện hiệu suất kết nối băm.
Sắp xếp tăng dần
Khi một truy vấn yêu cầu sắp xếp trên một tập hợp con các cột đã được sắp xếp theo một chỉ mục, PostgreSQL có thể thực hiện "sắp xếp tăng dần". Điều này tránh một thao tác sắp xếp đầy đủ, giảm đáng kể chi phí.
-- Assume an index on (order_date, customer_id)
CREATE INDEX idx_orders_date_customer ON orders (order_date, customer_id);
-- Query that can benefit from incremental sort
EXPLAIN (ANALYZE)
SELECT *
FROM orders
WHERE order_date >= '2023-01-01'
ORDER BY order_date, customer_id, order_total DESC;
Đầu ra EXPLAIN có thể hiển thị:
QUERY PLAN
--------------------------------------------------------------------------------------
Sort (cost=... rows=... width=...) (actual time=... rows=... loops=1)
Sort Key: order_total DESC
Presorted Key: order_date, customer_id <-- Indicates incremental sort
-> Index Scan using idx_orders_date_customer on orders (cost=... rows=... width=...) (actual time=... rows=... loops=1)
Index Cond: (order_date >= '2023-01-01'::date)
Dòng Presorted Key là chỉ báo chính. Để tối ưu hóa:
- Đảm bảo các chỉ mục của bạn bao gồm các cột dẫn đầu của mệnh đề
ORDER BYcủa bạn. - Các cột
Sort Keycòn lại sẽ được sắp xếp tăng dần.
Kết nối băm
Kết nối băm hiệu quả để kết nối các tập dữ liệu lớn, không được sắp xếp. PostgreSQL 17 cải thiện việc sử dụng bộ nhớ và xử lý tràn của chúng.
- Bộ nhớ: Đảm bảo
work_memđủ để chứa bảng băm của quan hệ nhỏ hơn trong bộ nhớ. Nếu nó tràn ra đĩa, hiệu suất sẽ giảm. - Xây dựng so với thăm dò: Trình lập kế hoạch thường xây dựng bảng băm trên quan hệ nhỏ hơn và thăm dò nó bằng quan hệ lớn hơn. Nếu trình lập kế hoạch chọn sai, nó có thể dẫn đến việc sử dụng bộ nhớ quá mức hoặc tràn.
enable_hashjoin: Đảm bảo GUC này làon(mặc định).
-- Example: Hash Join
EXPLAIN (ANALYZE, BUFFERS)
SELECT a.id, b.value
FROM large_table_a a
JOIN medium_table_b b ON a.b_id = b.id;
Đầu ra:
QUERY PLAN
--------------------------------------------------------------------------------------
Hash Join (cost=... rows=... width=...) (actual time=... rows=... loops=1)
Hash Cond: (a.b_id = b.id)
Buffers: ...
-> Seq Scan on large_table_a a (cost=... rows=... width=...) (actual time=... rows=... loops=1)
Buffers: ...
-> Hash (cost=... rows=... width=...) (actual time=... rows=... loops=1)
Memory: 12345kB <-- Hash table memory usage
Buffers: ...
-> Seq Scan on medium_table_b b (cost=... rows=... width=...) (actual time=... rows=... loops=1)
Buffers: ...
Nếu Memory trong nút Hash được theo sau bởi Disk, điều đó có nghĩa là bảng băm đã tràn. Tăng work_mem.
Thực thi truy vấn song song
PostgreSQL 17 tiếp tục tăng cường khả năng truy vấn song song, cho phép nhiều lõi CPU hoạt động trên các phần của một truy vấn duy nhất.
max_parallel_workers_per_gather: Kiểm soát số lượng worker song song tối đa có thể được khởi chạy cho một nútGatherhoặcGather Mergeduy nhất.max_parallel_workers: Tổng số worker song song được phép trên toàn hệ thống.min_parallel_table_scan_size: Kích thước bảng tối thiểu (tính bằng KB) để xem xét quét song song.parallel_setup_cost: Chi phí ước tính để khởi chạy các worker song song.parallel_tuple_cost: Chi phí ước tính để chuyển một tuple từ worker sang leader.
Xác định các kế hoạch song song:
Tìm các nút Gather hoặc Gather Merge trong đầu ra EXPLAIN ANALYZE.
EXPLAIN (ANALYZE, BUFFERS)
SELECT COUNT(*)
FROM very_large_table
WHERE some_column > 100;
Đầu ra:
QUERY PLAN
--------------------------------------------------------------------------------------
Finalize Aggregate (cost=... rows=... width=...) (actual time=... rows=... loops=1)
Buffers: ...
-> Gather (cost=... rows=... width=...) (actual time=... rows=... loops=1)
Workers Planned: 2
Workers Launched: 2
Buffers: ...
-> Partial Aggregate (cost=... rows=... width=...) (actual time=... rows=... loops=2)
Buffers: ...
-> Parallel Seq Scan on very_large_table (cost=... rows=... width=...) (actual time=... rows=... loops=2)
Filter: (some_column > 100)
Buffers: ...
Tối ưu hóa:
- Đảm bảo
max_parallel_workers_per_gatherđược đặt phù hợp (ví dụ:4đến8trên một máy chủ hiện đại). - Đối với các bảng thường xuyên được quét và lớn, đảm bảo
min_parallel_table_scan_sizekhông quá cao. - Song song hóa hiệu quả nhất cho các thao tác bị giới hạn bởi CPU trên các tập dữ liệu lớn (ví dụ: quét tuần tự lớn, tổng hợp, kết nối băm). Nó ít hiệu quả hơn đối với quét chỉ mục hoặc các truy vấn trả về ít hàng.
So sánh kiến trúc và đánh đổi
| Tính năng/Tham số | Mô tả | Mặc định (PG17) | Phạm vi khuyến nghị | Đánh đổi |
|---|---|---|---|---|
work_mem | Bộ nhớ cho các thao tác sắp xếp/băm trên mỗi truy vấn. | 4MB | 64MB - 256MB | Quá thấp: tràn đĩa, truy vấn chậm. Quá cao: OOM cho các truy vấn đồng thời. |
maintenance_work_mem | Bộ nhớ cho VACUUM, CREATE INDEX. | 64MB | 256MB - 1GB+ | Quá thấp: bảo trì chậm. Quá cao: ảnh hưởng đến các truy vấn đang hoạt động trong quá trình bảo trì. |
shared_buffers | Bộ đệm dữ liệu chính. | 128MB | 25% - 40% RAM | Quá thấp: I/O đĩa cao. Quá cao: dư thừa bộ đệm OS, OOM. |
effective_cache_size | Ước tính của trình lập kế hoạch về OS + shared_buffers. | 4GB | 50% - 75% RAM | Thông tin cho trình lập kế hoạch; không cấp phát bộ nhớ. Giá trị không chính xác dẫn đến các kế hoạch kém. |
max_parallel_workers_per_gather | Số worker song song tối đa trên mỗi truy vấn. | 2 | 4 - 8 | Quá thấp: không tận dụng hết CPU. Quá cao: chuyển đổi ngữ cảnh quá mức, tranh chấp tài nguyên. |
default_statistics_target | Mức độ chi tiết của thống kê. | 100 | 200 - 1000 | Quá thấp: ước tính hàng kém. Quá cao: tăng thời gian ANALYZE, bảng pg_statistic lớn hơn. |
Các vấn đề và khắc phục sự cố trong sản xuất
-
Vấn đề: Hiệu suất giảm đột ngột sau
VACUUM FULLhoặcREINDEX- Chế độ lỗi: Các truy vấn từng nhanh trở nên chậm, thường với
Seq Scanthay thếIndex Scan. - Nguyên nhân gốc:
VACUUM FULLvàREINDEXghi lại các bảng/chỉ mục, có khả năng dẫn đến trạng thái tạm thời mà thống kê bị cũ hoặc bộ đệm của trình lập kế hoạch bị vô hiệu hóa. - Khắc phục: Chạy ngay
ANALYZE VERBOSE;trên các bảng bị ảnh hưởng hoặc toàn bộ cơ sở dữ liệu sau các thao tác đó. Điều này buộc trình lập kế hoạch phải xây dựng lại thống kê chính xác. Đối vớiREINDEX, đảm bảoANALYZEđược chạy trên bảng sau khi chỉ mục được xây dựng lại.
- Chế độ lỗi: Các truy vấn từng nhanh trở nên chậm, thường với
-
Vấn đề:
work_memtràn mặc dù cài đặt cao- Chế độ lỗi:
EXPLAIN ANALYZEhiển thịSort Method: external merge DiskhoặcHashAggregate ... Diskngay cả khiwork_memđược đặt ở giá trị dường như cao (ví dụ:256MB). - Nguyên nhân gốc:
work_memđược cấp phát cho mỗi thao tác. Một truy vấn phức tạp duy nhất có thể có nhiều thao tác sắp xếp hoặc băm, mỗi thao tác tiêu thụwork_mem. Ngoài ra, nếu nhiều truy vấn đồng thời đang chạy, tổng mức tiêu thụ bộ nhớ có thể vượt quá RAM hệ thống. - Khắc phục:
- Xác định thao tác cụ thể: Xác định nút nào đang tràn.
- Tăng
work_memthêm: Nếu đó là một truy vấn đơn lẻ, quan trọng, hãy thử tăngwork_memcho phiên đó. - Tối ưu hóa truy vấn: Có thể tránh sắp xếp/băm không? Thêm chỉ mục cho
ORDER BYhoặcGROUP BY. Tái cấu trúc truy vấn để giảm kích thước tập dữ liệu trước khi sắp xếp/băm. - Giám sát tổng bộ nhớ: Sử dụng
pg_stat_activityđể xemtemp_bytescho các truy vấn đang hoạt động. Nếu tổngtemp_bytestrên tất cả các truy vấn cao, bạn có thể đang đạt đến giới hạn hệ thống.
- Chế độ lỗi:
-
Vấn đề: Trình lập kế hoạch chọn thứ tự kết nối không tối ưu
- Chế độ lỗi: Một truy vấn liên quan đến nhiều kết nối chạy rất chậm và
EXPLAIN ANALYZEhiển thị thứ tự kết nối xử lý một tập hợp kết quả trung gian lớn sớm. - Nguyên nhân gốc: Ước tính hàng không chính xác cho các kết quả trung gian, thường do thống kê cũ hoặc các mệnh đề
WHEREphức tạp mà trình lập kế hoạch không thể ước tính chính xác. - Khắc phục:
ANALYZE: Đảm bảo tất cả các bảng liên quan có thống kê cập nhật.CREATE STATISTICS: Đối với các tương quan đa cột hoặc phụ thuộc chức năng, hãy tạo thống kê mở rộng.sqlCREATE STATISTICS my_correlation_stats ON (col1, col2) FROM my_table; ANALYZE my_table;- Đơn giản hóa các mệnh đề
WHERE: Nếu có thể, hãy chia nhỏ các vị ngữ phức tạp. SET join_collapse_limit/SET from_collapse_limit: Tạm thời giảm các GUC này để buộc trình lập kế hoạch xem xét nhiều thứ tự kết nối hơn, mặc dù điều này có thể làm tăng thời gian lập kế hoạch.SET enable_nestloop = off;: Tạm thời vô hiệu hóa các loại kết nối cụ thể để buộc trình lập kế hoạch xem xét các lựa chọn thay thế, hữu ích cho việc gỡ lỗi.
- Chế độ lỗi: Một truy vấn liên quan đến nhiều kết nối chạy rất chậm và
-
Vấn đề:
Planning Timecao trongEXPLAIN ANALYZE- Chế độ lỗi:
Planning Timeliên tục cao (ví dụ: hàng trăm mili giây đến vài giây), ngay cả đối với các truy vấn đơn giản. - Nguyên nhân gốc:
- Truy vấn phức tạp: Nhiều kết nối, truy vấn con hoặc các thao tác
UNION. default_statistics_targetcao: Mặc dù tốt cho độ chính xác, các giá trị cao hơn có nghĩa là nhiều dữ liệu hơn để xử lý trong quá trình lập kế hoạch.enable_seqscan = off: Buộc quét chỉ mục ở mọi nơi có thể khiến trình lập kế hoạch làm việc vất vả hơn để tìm một chỉ mục.- Phiên bản PostgreSQL lỗi thời: Các phiên bản cũ hơn có trình lập kế hoạch kém hiệu quả hơn cho một số kịch bản phức tạp nhất định.
- Truy vấn phức tạp: Nhiều kết nối, truy vấn con hoặc các thao tác
- Khắc phục:
- Đơn giản hóa truy vấn: Chia nhỏ các truy vấn rất phức tạp thành các truy vấn nhỏ hơn, dễ quản lý hơn, có thể sử dụng CTE hoặc bảng tạm thời.
- Tham số hóa truy vấn: Nếu cấu trúc truy vấn giống hệt nhau nhưng chỉ các giá trị thay đổi, hãy sử dụng các câu lệnh đã chuẩn bị để bù đắp chi phí lập kế hoạch.
- Xem xét GUC: Đảm bảo
default_statistics_targetkhông quá cao đối với khối lượng công việc của bạn. - Nâng cấp PostgreSQL: Các phiên bản mới hơn thường có những cải tiến về trình lập kế hoạch.
- Chế độ lỗi:
Các câu hỏi thường gặp
-
Làm cách nào để biết
work_memcủa tôi được đặt đúng cách? Kiểm tra đầu raEXPLAIN ANALYZEđể tìmSort Method: external merge DiskhoặcHashAggregate ... Disk. Nếu chúng xuất hiện,work_memquá thấp cho thao tác cụ thể đó. Ngoài ra, hãy giám sátpg_stat_statementsđể tìmtemp_bytesvàtemp_filesđể xem tổng mức sử dụng tệp tạm thời. -
Khi nào tôi nên sử dụng
CREATE STATISTICS? Sử dụngCREATE STATISTICSkhi trình lập kế hoạch liên tục đưa ra các ước tính hàng kém cho các truy vấn liên quan đến nhiều cột trong các mệnh đềWHERE, điều kiệnJOINhoặc các mệnh đềGROUP BY, đặc biệt nếu các cột này có dữ liệu tương quan. Điều này giúp trình lập kế hoạch hiểu các mối quan hệ giữa các cột mà thống kê một cột bỏ qua. -
Sự khác biệt giữa
shared_buffersvàeffective_cache_sizelà gì?shared_bufferslà bộ nhớ thực tế mà PostgreSQL cấp phát cho bộ đệm dữ liệu của nó.effective_cache_sizelà một GUC cho trình lập kế hoạch truy vấn biết lượng bộ nhớ mà nó mong đợi có sẵn để lưu trữ dữ liệu, bao gồmshared_buffersvà bộ đệm hệ thống tệp OS. Nó không cấp phát bộ nhớ mà ảnh hưởng đến ước tính chi phí I/O đĩa của trình lập kế hoạch. -
Truy vấn của tôi đang sử dụng
Seq Scanthay vìIndex Scanngay cả khi có chỉ mục. Tại sao? Điều này thường xảy ra khi trình lập kế hoạch ước tính rằng quét tuần tự sẽ nhanh hơn quét chỉ mục. Các lý do phổ biến bao gồm:- Tính chọn lọc cao: Truy vấn đang truy xuất một tỷ lệ lớn các hàng từ bảng (ví dụ: >5-10%). Quét chỉ mục liên quan đến I/O ngẫu nhiên, có thể chậm hơn đọc tuần tự đầy đủ cho nhiều hàng.
- Thống kê cũ: Ước tính hàng của trình lập kế hoạch không chính xác. Chạy
ANALYZE. - Kích thước bảng: Đối với các bảng rất nhỏ,
Seq Scanthường nhanh hơn do chi phí truy cập chỉ mục. random_page_cost: Nếu GUC này được đặt quá cao, nó làm cho I/O ngẫu nhiên (quét chỉ mục) có vẻ tốn kém hơn.- Phình chỉ mục: Một chỉ mục bị phình to có thể làm cho việc quét chỉ mục không hiệu quả.
REINDEXcó thể giúp ích.
-
Làm cách nào để buộc PostgreSQL sử dụng một kế hoạch cụ thể? Mặc dù nói chung không được khuyến khích vì nó có thể dẫn đến các kế hoạch không tối ưu nếu dữ liệu thay đổi, bạn có thể ảnh hưởng đến trình lập kế hoạch bằng cách tạm thời vô hiệu hóa một số loại kế hoạch nhất định bằng cách sử dụng GUC (ví dụ:
SET enable_seqscan = off;,SET enable_nestloop = off;). Để kiểm soát chi tiết hơn, các công cụ nhưpg_hint_plan(một tiện ích mở rộng) cho phép các gợi ý cấp SQL, nhưng điều này nên được sử dụng hết sức thận trọng và chỉ sau khi thử nghiệm kỹ lưỡng. Cách tiếp cận tốt nhất là khắc phục các vấn đề về thống kê hoặc lập chỉ mục cơ bản.
Free In-Browser Developer Tools
Clean AI CLI logs, build cron expressions, decode JWTs, and calculate chmod permissions offline.
Related Articles
PostgreSQL Vacuum & Bloat Index: Phát hiện, Giảm thiểu và Tinh chỉnh Tự động
Chẩn đoán và loại bỏ tình trạng phình (bloat) bảng và index trong PostgreSQL. Nắm vững các công thức tinh chỉnh autovacuum, nén dữ liệu không downtime với pg_repack, và cơ chế visibility map của MVCC.
Read more
Các chiến lược Sharding cơ sở dữ liệu hiện đại cho tăng trưởng siêu tốc
Nắm vững các kiến trúc sharding cơ sở dữ liệu hiện đại: phân vùng ngang, khóa băm theo dải so với khóa băm nhất quán, kết nối liên shard, giao dịch phân tán (2PC so với Saga), Vitess và Citus.
Read more
Phân vùng gốc PostgreSQL so với TimescaleDB: Điểm chuẩn chuỗi thời gian nhập liệu cao
Hướng dẫn toàn diện so sánh phân vùng gốc PostgreSQL với TimescaleDB: điểm chuẩn chuỗi thời gian nhập liệu cao với kiến trúc cấp độ sản xuất và các ví dụ mã.
Read more