Mỗi một lập trình viên thường phải làm việc với rất nhiều câu lệnh truy vấn SQL mỗi ngày. Vì vậy, hiểu được cách để tối ưu hóa câu lệnh SQL là rất quan trọng, vì nó sẽ giúp cho hiệu suất hệ thống tăng lên đáng kể và giảm thời gian chờ đợi của người dùng.
Bắt đầu từ FROM và JOIN
Đầu tiên mệnh đề FROM và JOIN sẽ được thực hiện trước:
Ở bước này chúng ta lựa chọn các table (bảng) mà chúng ta sẽ làm việc và chỉ rõ cách để kết nối chúng lại với nhau. Thông thường ở bước này chúng ta sẽ sử dụng ID để so khớp và kết nối 02 bảng với nhau.
ON
Dựa vào ID, cụ thể ở đây là ID của customer (customers.id = orders.customer_id) để liên kết hai bảng với nhau. Kết quả cho ra một tập dữ liệu có chứa thông tin ID của customer ở cả 2 bảng. Do đó việc sử dụng cột được đánh index sẽ tăng đáng kể hiệu suất của mệnh đề JOIN
Indexing sử dụng B-Tree hoặc Bitmap Index sẽ ảnh hưởng tới hiệu suất của câu truy vấn.
WHERE
Tiếp đến, mệnh đề WHERE giúp lọc lại giữ liệu dựa vào điều kiện. Trong ví dụ này, chúng ta sử dụng điều kiện nói rằng: ORDER_DATE >= ‘2023-01-01’ ~ tức là ngày đặt hàng từ ngày 1/1/2023
Tại đây, chúng ta cần chú ý sử dụng các câu lệnh SARGABLE (Search Argument Able) chỉ các câu lệnh có thể sử dụng indexing để tăng tốc độ thực thi.
Chi tiết hơn về SARGABLE query:
Đây là những lỗi mà lập trình viên rất thường gặp khi không có kiến thức đủ sâu về bản chất của các câu lệnh truy vấn SQL.
Ở ví dụ trên, với Non-Sargable query, để lọc ra dữ liệu cần thiết trên 100.000 bản ghi thì máy tính cần thực hiện 100.000 lần hàm YEAR để lấy ra năm của order_date, sau đó so sánh với 2023. Với Sargable query, chúng ta so sánh trực tiếp order_date với một ngày cụ thể, cho phép database engine sử dụng index để nhanh chóng lọc ra các bản ghi thỏa mãn điều kiện.
Để viết các Sargable query, ta cần:
- Tránh sử dụng các hàm hoặc tính toán trên các cột đã đánh index trong mệnh đề WHERE.
- Sử dụng so sánh trực tiếp bất kì khi nào có thể.
- Nếu cần phải sử dụng hàm trên một cột nào đó, ta nên xem xét tạo ra một cột chứa kết quả tính toán hoặc một index dựa trên hàm nếu như hệ quản trị cơ sở dữ liệu hỗ trợ
GROUP BY
Tiếp theo, chúng ta nhóm các kết quả lại theo customer_id.
HAVING
Lọc những khách hàng có total_spent >= 1000.
SELECT
Lựa chọn những cột mà chúng ta muốn bằng mệnh đề SELECT. Trong trường hợp này chúng SELECT cột customer_id, total_orders và total_spent.
Mặc dù SELECT nằm ở đầu tiên trong câu truy vấn nhưng lại nằm gần cuối trong quy trình thực thi các mệnh đề của câu lệnh truy vấn. Do đó để tối ưu hóa câu truy vấn, chúng ta cần tối ưu mệnh đề SELECT, WHERE, JOIN để giúp hệ quản trị cơ sở dữ liệu sử dụng index để thực thi các mệnh đề, nhanh chóng cho ra kết quả, giảm thiểu việc sử dụng tài nguyên…
ORDER BY
Sắp xếp lại kết quả trên.
LIMIT
Giữ lại số lượng kết quả chỉ định.
Như vậy, thông qua ví dụ trên chúng ta hiểu rõ trật tự thực thi một câu truy vấn SQL và cách để tối ưu hóa một câu truy vấn SQL như thế nào. Hãy đọc kỹ bài viết và thực hành để nhớ lâu hơn nhé!
Bộ môn Ứng dụng phần mềm
Trường Cao đẳng FPT Polytechnic cơ sở Đà Nẵng