SQL调优和SQL优化

本文为译文i,翻译自原文 http://beginner-sql-tutorial.com/sql-query-tuning.htm

sql语句可以用来从数据库取回数据。不同的sql查询语句有时可以得到相同的返回结果。如果考虑执行效率的话,选择使用最佳的查询语句至关重要,所以我们需要根据需求来优化sql查询。下面是一些我们平时经常使用的查询语句,以及如何优化它们以达到更好的执行效率。

SQL调优/SQL优化技巧:

1) 如果在SELECT语句里面用具体的column名而不是’*’,sql查询会更快。

例如,查询语句写成:

SELECT id, first_name, last_name, age, subject FROM student_details;

比写成下面这样快:

SELECT * FROM student_details;


2) HAVING字句是用来进一步过滤SELECT查询结果的,它就像一个过滤器。别把HAVING用作其它任何用途。

例如,写成:

SELECT subject, COUNT(subject)
FROM student_details
WHERE subject != 'Science'
AND subject != 'Maths'
GROUP BY subject;

而不是:

SELECT subject, COUNT(subject)
FROM student_details
GROUP BY subject
HAVING subject!= 'Vancouver' AND subject!= 'Toronto';

3) 有时候在主查询语句里面可能包含不止一个子查询语句。尽量减少子查询语句的数量有助于提高效率。

例如,写成:

SELECT name
FROM employee
WHERE (salary, age ) = (SELECT MAX (salary), MAX (age)
FROM employee_details)
AND dept = 'Electronics';

而不是:

SELECT name
FROM employee
WHERE salary = (SELECT MAX(salary) FROM employee_details)
AND age = (SELECT MAX(age) FROM employee_details)
AND emp_dept = 'Electronics';

4) 恰当的使用EXISTS,IN和table joins。

a) IN通常效率最低
b) 当大多数过滤条件存在在子查询语句里面的时候,IN效率更高
c) 当大多数过滤条件存在在主查询语句的时候,EXISTS效率更高

例如,写成:

SELECT * FROM product p
WHERE EXISTS (SELECT * FROM order_items o
WHERE o.product_id = p.product_id)

而不是:

SELECT * FROM product p
WHERE product_id IN
(SELECT product_id FROM order_items

5) 当join的两个表包含一对多关系时,优先使用EXISTS而不是DISTINCT。

例如,写成:

SELECT d.dept_id, d.dept
FROM dept d
WHERE EXISTS ( SELECT 'X' FROM employee e WHERE e.dept = d.dept);

而不是:

SELECT DISTINCT d.dept_id, d.dept
FROM dept d,employee e
WHERE e.dept = e.dept;

6) 尝试使用UNION ALL来替换UNION。

例如,写成:

SELECT id, first_name
FROM student_details_class10
UNION ALL
SELECT id, first_name
FROM sports_team;

而不是:

SELECT id, first_name, subject
FROM student_details_class10
UNION
SELECT id, first_name
FROM sports_team;

7) 当在WHERE子句里面使用条件判断时,要小心。

例如,写成:

SELECT id, first_name, age FROM student_details WHERE age > 10;

而不是:

SELECT id, first_name, age FROM student_details WHERE age != 10;

写成:

SELECT id, first_name, age
FROM student_details
WHERE first_name LIKE 'Chan%';

而不是:

SELECT id, first_name, age
FROM student_details
WHERE SUBSTR(first_name,1,3) = 'Cha';

写成:

SELECT id, first_name, age
FROM student_details
WHERE first_name LIKE NVL ( :name, '%');

而不是:

SELECT id, first_name, age
FROM student_details
WHERE first_name = NVL ( :name, first_name);

写成:

SELECT product_id, product_name
FROM product
WHERE unit_price BETWEEN MAX(unit_price) AND MIN(unit_price)

而不是:

SELECT product_id, product_name
FROM product
WHERE unit_price >= MAX(unit_price)
AND unit_price <= MIN(unit_price)

写成:

SELECT id, name, salary
FROM employee
WHERE dept = 'Electronics'
AND location = 'Bangalore';

而不是:

SELECT id, name, salary
FROM employee
WHERE dept || location= 'ElectronicsBangalore';

把非column表达式放在查询语句的一边,因为它们会被优先处理。

写成:

SELECT id, name, salary
FROM employee
WHERE salary < 25000;

而不是:

SELECT id, name, salary
FROM employee
WHERE salary + 10000 < 35000;

写成:

SELECT id, first_name, age
FROM student_details
WHERE age > 10;

而不是:

SELECT id, first_name, age
FROM student_details
WHERE age NOT = 10;

使用DECODE来避免重复扫描同一条数据或重复join同一张表。DECODE也可以用来替换GROUP BY或ORDER BY子句。

例如,写成:

SELECT id FROM employee
WHERE name LIKE 'Ramesh%'
AND location = 'Bangalore';

而不是:

SELECT DECODE(location,'Bangalore',id,NULL) id FROM employee
WHERE name LIKE 'Ramesh%';

9) 存储大二进制数据,首先将其存储在文件系统上,然后将其文件路径存储到数据库。

10) 遵守SQL标准规则。

a) 对所有的SQL动词使用同一种大小写
b) 所有的SQL动词放在新一行的开头
c) 所有的单词用一个空格分隔
d) 所有的SQL动词左对齐或右对齐首个SQL动词

[Footnotes]
  1. 翻译的主要目的在于强化记忆和加深理解 []

历史上的今天:

Related posts:

Got something to say? Go for it!

使用新浪微博登陆