Tôi nhận được nhiều câu hỏi cũng như yêu cầu hỗ trợ để tối ưu
hóa câu lệnh SQL trong Oracle trong thời gian gần đây từ các bạn sinh
viên và anh em mới sử dụng Oracle. Trong bài viết này tôi tập hợp và cụ
thể hóa lại các trường hợp cần tối ưu khi làm việc với SQL trong Oracle.
Tối ưu hóa câu lệnh SQL trong Oracle
Cần tối ưu hóa câu lệnh truy vấn đến các bảng được đánh index và partition
Trong các hệ thống lớn, có nhiều bảng có dữ liệu lớn, khi tạo bảng người
thiết kế phải thực hiện đánh index, partition để tăng tốc độ truy vấn
dữ liệu. Vì thế khi viết câu lệnh truy vấn các bạn nên lưu ý một số
nguyên tắc để có thể tối ưu hóa thời gian thực hiện câu lệnh:
1. Không khuyên khích sử dụng hàm đối với các trường được đánh index, partition:
Mã:
SELECT *
FROM users
WHERE UPPER (username) = UPPER ('USERNAME'); -- trường username thường được đánh index, nên dùng hàm UPPER() sẽ giảm tốc độ truy vấn
2. Hạn chế dùng toán tử not like, not in, <> với trường được đánh index, partition
Mã:
SELECT *
FROM users
WHERE username NOT LIKE 'USER_NAME%'; -- ở đây trường username được đánh index
SELECT *
FROM users
WHERE username NOT IN ('USERNAME_ONE', 'USERNAME_TWO', 'USERNAME_THREE'); -- ở đây trường username được đánh index
SELECT *
FROM users
WHERE username <> 'USERNAME';-- ở đây trường username được đánh index
3. Hạn chế sử dụng like ‘%str’
Mã:
SELECT *
FROM users
WHERE username LIKE '%USERNAME';-- ở đây trường username được đánh index
Khi nào nên dùng IN và dùng EXISTS
Để quyết định dùng toán tử IN hay EXISTS khi nào chúng ta thực hiện đánh giá sau:
1. Hiểu bản chất toán tử IN
Mã:
SELECT *
FROM table1
WHERE r1 IN (SELECT r2
FROM table2);
--Câu lệnh trên tương đương với câu lệnh dưới
SELECT *
FROM table1,
(SELECT DISTINCT r2
FROM table2) table2
WHERE table1.r1 = table2.r2;
Câu lệnh này quét dữ liệu full bảng table2 vì nó thực hiện câu
lệnh SELECT DISTINCT r2 FROM table2. Nhưng bảng dữ liệu T2 mà lớn thì
thời gian thực hiện câu lệnh sẽ rất chậm
2.Bản chất câu lệnh dùng Exists
Mã:
SELECT DISTINCT pub_name
FROM table1
WHERE EXISTS
(SELECT *
FROM table2 where username='USERNAME');
Câu lệnh này quét dữ liệu full bảng table2 dẫn đến lệnh truy vấn chạy chậm
Như vậy:
- Chúng ta dùng IN khi dữ liệu bảng table1 lớn hơn dữ liệu ở bảng table2
- Chúng ta dùng Exists khi dữ liệu bảng table2 lớn hơn dữ liệu bảng table1, 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
Chúc các bạn thành công
0 nhận xét:
Đăng nhận xét