Tối Ưu Hóa Câu Lệnh SQL (Part 2)

QA/QC Mar 04, 2022

Mọi người có thể tìm đọc Part 1 tại link sau nhé:

https://tech.miichisoft.net/toi-uu-hoa-cau-lenh-sql/

2.4. Toán tử so sánh 2 lần

Hạn chế sử dụng phép toán so sánh 2 lần như “<=”, “>=” với những trường đánh index (bản chất của phép toán này là phép toán OR)

Ví dụ:

Ta có câu lệnh Lấy ra UserId và Username từ bảng Users, Số lượng (Amount) lớn hơn hoặc bằng 15.

SELECT UserId, Username FROM Users WHERE Amount >= 15;

Câu lệnh trên tương ứng với câu lệnh sau :

SELECT UserId, Username FROM Users WHERE Amount > 15 OR Amount = 15;

=> Câu lệnh này sẽ khiến SQL phải so sánh 2 lần: Amount > 15 OR Amount = 15. Do đó làm chậm truy vấn.

Vì vậy, nên dùng câu lệnh dưới đây cho tình huống tương tự:

SELETC UserId, Username FROM Users WHERE Amount > 14;

2.5. Hạn chế sử dụng function lên column


Ta có câu lệnh xác định danh sách member có tuổi lớn hơn 21.

SELECT member_number, first_name, last_name

FROM Members

WHERE DATEDIFF(yy,dateofbirth,GETDATE()) > 21;

=> Ở câu lệnh trên thì Hàm DATEDIFF đã tác động trực tiếp tới trường DateOfBirth.

Sau khi tính toán bởi hàm DATEDIFF thì SQL không thể dùng Index cho column dateofbirth được nữa.

Sử dụng câu truy vấn như dưới đây sẽ nhanh hơn:

ELECT member_number, first_name, last_name

FROM Members

WHERE dateofbirth < DATEADD(yy,-21,GETDATE());

2.6. Tránh sử dụng câu truy vấn cùng like với ‘%’ phía trước


Lệnh truy vấn tìm kiếm theo like

SELECT * FROM Customers

WHERE CustomerName LIKE '%A';

Phần % đầu tiên là giá trị kết thúc bằng A’

Câu truy vấn này  phải duyệt toàn bộ bảng để tìm kiếm các bản ghi thỏa mãn yêu cầu.


SELECT * FROM Customers

WHERE MATCH(CustomerName) AGAINST('*A' IN BOOLEAN MODE )

Trong ví dụ bên trên, chúng ta đã xác định cột mà muốn match (CustomerName) tìm kiếm với ký tự cuối cùng là A

2. 7. Tối ưu hóa câu lệnh bằng Union

Ta có câu lệnh sau:

SELECT memId, memName, memPhone

FROM Members

WHERE dept = 'QA' or level = 'junior' or division = '1';


Cả 2 câu truy vấn đều phải quét toàn bộ table như nhau, tuy nhiên câu truy vấn trên tiêu tốn phần phần lớn thời gian cho thao tác 「Distinct sort」để loại bỏ những bản ghi trùng nhau (mặc dù không hề có những bản ghi như vậy). Thay vào đó  nên sử dụng:


SELECT memId, memName, memPhone FROM Members

WHERE dept = 'QA' UNION ALL

SELECT memId, memName, memPhone FROM Members

WHERE level = 'junior' UNION ALL

SELECT memId, memName, memPhone FROM Members

WHERE division = '1'


2.8. Đánh index ở các cột sử dụng where, order by, group by

Ta có câu truy vấn sau:

SELECT * FROM Orders

WHERE YEAR(finished_at) = ‘2021’


Chúng ta sử dụng function YEAR cùng với cột finished_at nó sẽ không cho phép database sử dụng index ở cột finished_at bởi vì index giá trị của finished_at chứ không phải YEAR(finished_at).

Để có thể tránh được điều này ta có thể sử dụng index cho function bằng generated columns hoặc một cách khác là tìm cách để viết lại câu truy vấn tương đương mà không phải sử dụng đến function:


SELECT * FROM Orders

WHERE finished_at >= '2021-01-01' AND finished_at < '2022-01-01';






Tags

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.