Trong bài viết trước của tôi, chúng tôi đã bắt đầu mô tả khái niệm cơ bản về lệnh EXPLAIN và phân tích những gì xảy ra trong PostgreSQL khi thực thi một truy vấn.
Tôi sẽ tiếp tục viết về những điều cơ bản của GIẢI THÍCH trong PostgreSQL. Thông tin là một đánh giá ngắn về Hiểu GIẢI THÍCH của Guillaume Lelarge. Tôi thực sự khuyên bạn nên đọc bản gốc vì một số thông tin bị bỏ sót.
Bộ nhớ đệm
Điều gì xảy ra ở cấp vật lý khi thực hiện truy vấn của chúng tôi? Hãy tìm hiểu nó. Tôi đã triển khai máy chủ của mình trên Ubuntu 13.10 và sử dụng bộ đệm đĩa ở cấp hệ điều hành.
Tôi dừng PostgreSQL, thực hiện các thay đổi đối với hệ thống tệp, xóa bộ nhớ cache và chạy PostgreSQL:
> sudo service postgresql-9.3 stop > sudo sync > sudo su - # echo 3 > /proc/sys/vm/drop_caches # exit > sudo service postgresql-9.3 start
Khi bộ nhớ cache bị xóa, hãy chạy truy vấn với tùy chọn BUFFERS
EXPLAIN (ANALYZE,BUFFERS) SELECT * FROM foo;
Chúng tôi đọc bảng theo khối. Bộ nhớ đệm trống. Chúng tôi phải truy cập 8334 khối để đọc toàn bộ bảng từ đĩa.
Bộ đệm:đọc được chia sẻ là số khối mà PostgreSQL đọc từ đĩa.
Chạy truy vấn trước đó
EXPLAIN (ANALYZE,BUFFERS) SELECT * FROM foo;
Bộ đệm:lượt truy cập được chia sẻ là số khối được truy xuất từ bộ đệm PostgreSQL.
Với mỗi truy vấn, PostgreSQL lấy ngày càng nhiều dữ liệu từ bộ nhớ cache, do đó, lấp đầy bộ nhớ cache của chính nó.
Thao tác đọc bộ nhớ đệm nhanh hơn thao tác đọc đĩa. Bạn có thể thấy xu hướng này bằng cách theo dõi Tổng giá trị thời gian chạy.
Kích thước bộ nhớ đệm được xác định bởi hằng số shared_buffers trong tệp postgresql.conf.
Ở ĐÂU
Thêm điều kiện vào truy vấn
EXPLAIN SELECT * FROM foo WHERE c1 > 500;
Không có chỉ mục nào trên bảng. Khi thực hiện truy vấn, mỗi bản ghi của bảng được quét tuần tự (Seq Scan) và so sánh với điều kiện c1> 500. Nếu điều kiện được đáp ứng, bản ghi sẽ được thêm vào kết quả. Nếu không, nó sẽ bị loại bỏ. Bộ lọc cho biết hành vi này, cũng như giá trị chi phí tăng lên.
Số lượng hàng ước tính giảm xuống.
Bài viết gốc giải thích tại sao chi phí lại lấy giá trị này và cách tính số hàng ước tính.
Đã đến lúc tạo chỉ mục.
CREATE INDEX ON foo(c1); EXPLAIN SELECT * FROM foo WHERE c1 > 500;
Số lượng hàng ước tính đã thay đổi. Còn chỉ số thì sao?
EXPLAIN (ANALYZE) SELECT * FROM foo WHERE c1 > 500;
Chỉ có 510 hàng trong số hơn 1 triệu hàng được lọc. PostgreSQL phải đọc hơn 99,9% bảng.
Chúng tôi sẽ buộc sử dụng chỉ mục bằng cách tắt Seq Scan:
SET enable_seqscan TO off; EXPLAIN (ANALYZE) SELECT * FROM foo WHERE c1 > 500;
Trong Quét lập chỉ mục và Điều kiện lập chỉ mục, chỉ mục foo_c1_idx được sử dụng thay vì Bộ lọc.
Khi chọn toàn bộ bảng, việc sử dụng chỉ mục sẽ làm tăng chi phí và thời gian để thực hiện truy vấn.
Bật quét tuần tự:
SET enable_seqscan TO on;
Sửa đổi truy vấn:
EXPLAIN SELECT * FROM foo WHERE c1 < 500;
Ở đây người lập kế hoạch sử dụng chỉ mục.
Bây giờ, hãy làm phức tạp giá trị bằng cách thêm trường văn bản.
EXPLAIN SELECT * FROM foo WHERE c1 < 500 AND c2 LIKE 'abcd%';
Như bạn có thể thấy, chỉ mục foo_c1_idx được sử dụng cho c1 <500. Để thực hiện c2 ~~ ‘abcd%’ ::text, hãy sử dụng bộ lọc.
Cần lưu ý rằng định dạng POSIX của toán tử LIKE được sử dụng trong đầu ra của kết quả. Nếu chỉ có trường văn bản trong điều kiện:
EXPLAIN (ANALYZE) SELECT * FROM foo WHERE c2 LIKE 'abcd%';
Quét Seq được áp dụng.
Xây dựng chỉ mục bằng c2:
CREATE INDEX ON foo(c2); EXPLAIN (ANALYZE) SELECT * FROM foo WHERE c2 LIKE 'abcd%';
Chỉ mục không được áp dụng vì cơ sở dữ liệu của tôi cho các trường thử nghiệm sử dụng mã hóa UTF-8.
Khi xây dựng chỉ mục, cần phải chỉ định lớp của toán tử text_pattern_ops:
CREATE INDEX ON foo(c2 text_pattern_ops); EXPLAIN SELECT * FROM foo WHERE c2 LIKE 'abcd%';
Tuyệt quá! Nó đã hoạt động!
Bitmap Index Scan sử dụng chỉ mục foo_c2_idx1 để xác định các bản ghi chúng ta cần. Sau đó, PostgreSQL chuyển đến bảng (Bitmap Heap Scan) để đảm bảo rằng các bản ghi này thực sự tồn tại. Hành vi này đề cập đến việc lập phiên bản của PostgreSQL.
Nếu bạn chỉ chọn trường, nơi chỉ mục được tạo, thay vì toàn bộ hàng:
EXPLAIN SELECT c1 FROM foo WHERE c1 < 500;
Chỉ Quét chỉ mục sẽ được thực hiện nhanh hơn Quét chỉ mục do thực tế là không cần thiết phải đọc hàng của bảng:width =4.
Kết luận
- Seq Scan đọc toàn bộ bảng
- Quét chỉ mục sử dụng chỉ mục cho các câu lệnh WHERE và đọc bảng khi chọn hàng
- Quét chỉ mục bitmap sử dụng Quét chỉ mục và kiểm soát lựa chọn thông qua bảng. Hiệu quả đối với một số lượng lớn hàng.
- Chỉ quét chỉ mục là khối nhanh nhất, chỉ đọc chỉ mục.
Đọc thêm:
Tối ưu hóa truy vấn trong PostgreSQL. GIẢI THÍCH Khái niệm cơ bản - Phần 3