Thứ Bảy, 5 tháng 3, 2016

Tối ưu hóa câu lệnh SQL trong Oracle


Thảo luận trong 'Oracle' bắt đầu bởi oranewbie, Hôm nay lúc 00:58.
oranewbie

oranewbie New Member

Bài viết:
5
Đã được thích:
0
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: