Bài viết nằm trong series Performance optimization với PostgreSQL.
Bài trước chúng ta đã biết về các phương pháp giúp tăng performance của SQL query. Bài hôm nay sẽ giới thiệu về một trong các phương pháp đó, indexing thần thánh.
Từ bài này sẽ liên quan nhiều đến practice nên các bạn chuẩn bị env và data trước. Mình sử dụng Docker cho nhanh.
Start PostgreSQL và pgAdmin4:
Tạo mới table:
Insert data 100k records tải ở đây nhé.
Trước khi optimize query, ta cần hiểu query đó thực hiện nhiệm vụ gì, có thể optimize phần nào, không thể ào ào thêm index hay chia partition và mong nó chạy nhanh hơn được. Xin lưu ý, chúng ta là các kĩ sư chuyên ngành, ở đây chúng ta không làm như thế
Explain & Analyze là công cụ đắc lực để thực hiện việc đó. Nó giúp giải thích các bước thực hiện trong câu query là gì với các thông số về cost, rows, widths… Việc còn lại của các kĩ sư là nhìn vào đó để biết vấn đề đang nằm ở đâu và xử lý ra sao (phần khó nhất
Explain keywork giải thích từng bước câu query được thực hiện, bắt đầu với query sau:
Với query trên, chỉ 1 step cần thực thi là sequence scan table, rất dễ hiểu. Điều chúng ta quan tâm là các con số đằng sau:
SELECT GENDER
thì giá trị width sẽ nhỏ và giá trị là 2 bytes (smallint).Trong thực tế, ta chỉ quan tâm đến cost, một con số áng chừng về execution time. Để có con số cụ thể hơn, ta thêm option analyze vào sau explain.
Lưu ý: analyze option sẽ thực thi các statement chứ không đơn thuần là plan nữa. Vì vậy cần rất cẩn thận khi thêm option này trong quá trình explain.
Ví dụ với các DML statement (INSERT/DELETE/UPDATE):
- Nếu chỉ thực hiện explain thì không có vấn đề gì xảy ra.
- Nếu thực hiện explain analyze thì.. còn cái nịt
.Image Not Showing Possible ReasonsLearn More →
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Do vậy, nếu muốn thực thi các DML statement với explain analyze, sử dụng như sau:
Tiếp tục xuất hiện một vài thông số:
Thử với query có điều kiện WHERE nhé:
Vẫn là seq scan table, tuy nhiên có thêm bước filter để lọc các row có giá trị national_id
>= 100. Không có gì khó hiểu lắm.
Bước phân tích tính toán query đã xong. Ta nhận thấy một vài vấn đề, trong đó có seq scan. Đã có bằng chứng trong tay, xử lý thôi.
Như đã giới thiệu trong bài trước, để tránh full table scan, ta dùng index
Thực hành trước đã, câu query trên sử dụng điều kiện với country_id, đánh index cho cột này trước:
Sau khi thêm index, chạy lại câu lệnh EXPLAIN ANALYZE SELECT * FROM ENGINEER
, kết quả không có gì thay đổi vì chẳng dính dáng gì tới country_id cả. Chạy với điều kiện WHERE
sử dụng country_id xem thế nào:
WTF, vẫn seq scan, chẳng có nhẽ các Senior bịp mình
Đã có chút thay đổi điều kiện >= 150, query plan sử dụng bitmap heap scan chính là bitmap index. Execution time giảm ~ 30% từ 1500 xuống 1011 ms. Vì sao có sự khác biệt này?
Với điều kiện >= 100, có rất nhiều records phù hợp. Do đó query execution xác định rằng seq scan trên table chính còn nhanh hơn việc scan index trên table index. Thông minh phết, hóa ra các Senior lương chục ngàn không bịp bợm
Lưu ý rằng, bài trước ta đã biết việc sử dụng index là việc scan trên 2 table. Tức là scan index table trước, sau đó ánh xạ kết quả sang table chính.
Như vậy với mỗi điều kiện khác nhau DB System sẽ biết cách thực hiện các query nhanh nhất có thể dựa trên những gì chúng ta cung cấp cho nó, cụ thể ở đây là index. Ngoài ra, ta thấy một lesson learn khác là đôi khi index không đem lại tác dụng gì. Đừng index vô tội vạ, không những không tăng tốc độ read mà còn làm chậm tốc độ write.
Cùng tìm hiểu về các loại index phổ biến trong Relational Database:
- B-Tree index.
- Hash index.
- Bitmap index.
Ngoài ra PostgreSQL có một số loại index đặc biệt:
- GIST.
- SP-GIST.
- GIN.
- BRIN.
Viết dài quá dễ quên, mình sẽ đi cụ thể từng loại index và ứng dụng thực tế trong bài viết sau nhé. Tổng kết bài viết rút ra 2 kết luận:
- Sử dụng explain và analyze option để phân tích query, tìm bottle neck.
- Sử dụng index để tăng tốc độ truy vấn.. và chỉ hữu ích trong một vài tình huống cụ thể.
© Dat Bui