Nguyên nhân

  • Những câu truy vấn chậm có thể phát sinh từ rất nhiều nguyên nhân bao gồm:
    • Không/thiếu sử dụng các lợi ích của Indexes.
    • Không/thiếu tận dụng được I/O striping.
    • Các thống kê lỗi thời hoặc thiếu các thống kê hữu ích.
    • Thiếu bộ nhớ vật lý.
    • Kết nối mạng chậm.
    • Các câu truy vấn Transact-SQL chuyển số lượng dữ liệu lớn từ server đến client.
    • Locks or deadlocks bị cấm.
    • Thực hiện các câu truy vấn OLTP and OLAP trên cùng 1 máy server.
    • Trả về các dữ liệu không cần thiết.
    • Các câu truy vấn được viết nghèo nàn.

Tối ưu hoá câu lệnh

Tối ưu hóa câu lệnh truy vấn với bảng đánh partition và index

- Vấn đề: Đối với những bảng có dữ liệu lớn, khi tạo bảng người thiết kế phải thực hiện một số kỹ thuật để tăng tốc độ truy vấn dữ liệu như đánh index, partition. Khi truy vấn người lập trình phải tuân thủ một số nguyên tắc để đảm bảo tối ưu hóa thời gian thực hiện câu lệnh:

  • Không nên sử dụng hàm đối với trường đánh index, partition:
-- khong nen su dung
SELECT *
  FROM users
 WHERE UPPER (user_name) = UPPER ('USER_NAME');
  • Không nên sử dụng sử dụng toán tử not like, not in, <> với trường đánh index, partition:
-- khong nen su dung
SELECT *
  FROM users
 WHERE user_name NOT LIKE 'USER_NAME%';
-- khong nen su dung
SELECT *
  FROM users
 WHERE user_name NOT IN ('USER_NAME1', 'USER_NAME2', 'USER_NAME3');
-- khong nen su dung
SELECT *
  FROM users
 WHERE user_name <> 'USER_NAME1';
  • Không nên sử dụng like ‘%str’
-- khong nen su dung
SELECT *
  FROM users
 WHERE user_name LIKE '%USER_NAME';
  • Lưu ý: Các trường hợp trên không nên sử dụng do làm mất tác dụng của cột đánh index

Khi nào dùng IN, khi nào dùng EXISTS

  • Vấn đề: Trong một số trường hợp dữ liệu lớn, khi cần sử dụng toán tử IN hoặc Exists trong câu lệnh có thể tốc độ thực thi câu lệnh khác nhau tương đối lớn. Để quyết định dùng toán tử nào ta dựa vào đánh giá sau:
  • Bản chất câu lệnh khi dùng toán tử IN
    • Câu lệnh này quét dữ liệu full bảng T2 khi thực hiện câu lệnh SELECT DISTINCT y FROM t2; nếu bảng dữ liệu T2 lớn thì thời gian thực hiện câu lệnh tương đối chậm.
SELECT *
  FROM t1
 WHERE x IN (SELECT y
               FROM t2);
--Dien giai (tuong duong voi cau lenh sau)
SELECT *
  FROM t1,
       (SELECT DISTINCT y
                   FROM t2) t2
 WHERE t1.x = t2.y;
  • Bản chất câu lệnh dùng Exists
    • Câu lệnh này quét dữ liệu full bảng T1, trường hợp bảng T2 đánh index theo trường y thì tốc độ truy vấn dữ liệu bảng T2 tương đối nhanh
for x in ( select * from t1 )
loop
   if ( exists ( select null from t2 where y = x.x ))
   then
       OUTPUT THE RECORD
   end if
end loop;
  • Dùng IN khi: Dữ liệu bảng T1 lớn hơn dữ liệu ở bảng T2
  • Dùng Exists khi: Dữ liệu bảng T2 lớn hơn dữ liệu bảng T1, trường điều kiện được đánh index
  • Nếu dữ liệu cả 2 bảng đều lớn, hoặc tương đương nhau thì 2 cách dùng có thời gian thực hiện tương đương nhau

Comment

Thêm bình luận mới