SQL优化必知技巧—— 避免排序
我们知道 sql 语言中,用户不能显示地命令数据库进行排序操作。对用户隐藏这样操作正式SQL的设计思想。但数据库有些命令会对结果进行排序,当数据量较大时,排序会非常耗时。本文我们讨论如何避免无谓的排序,提升SQL执行效率。
会进行排序的SQL 命令
下面列举会排序的代表性运算:
- GROUP BY 子句
- ORDER BY 子句
- 聚合函数(SUM,COUNT,AVG,MAX,MIN)
- DISTINCT
- 集合运算(UNICON,INTERSECT,EXCEPT)
- 窗口函数(RANK,ROW_NUMBER等)
示例说明
下面通过两个示例进行说明,分别是union 和 distinct。
尽可能使用 union all 代替 union
SELECT * FROM TABLE_A
UNION ALL
SELECT * FROM TABLE_B;
如果不在乎结果中存在重复数据,或预先知道结果中不会有重复数据。请使用union all 代替 union,这样就不会进行排序。
尽可能使用exists 代替 distinct
示例数据说明,下面有商品表和销售记录表。
Items:
item_no | item |
---|---|
10 | FD |
20 | CD-R |
30 | MO |
40 | DVD |
SalesHistory:
sale_date | item_no | item |
---|---|---|
2018-01-01 | 10 | 4 |
2018-01-01 | 20 | 5 |
2018-01-01 | 30 | 3 |
2018-01-03 | 10 | 7 |
2018-01-03 | 10 | 9 |
2018-01-04 | 20 | 2 |
2018-01-04 | 30 | 12 |
问题:查找有销售记录的商品。
当然我们可以使用in方式实现,但因为in会产生子查询,不如使用连接查询效率高。
SELECT DISTINCT I.item_no
FROM Items I INNER JOIN SalesHistory S
ON I.item_no = S.item_no;
因为是一对多查询,会产生重复记录,所有使用DISTINCT过滤重复记录。
但更好的做法是使用exists方式:
SELECT DISTINCT I.item_no
FROM Items I
WHERE EXISTS (
SELECT * FROM SalesHistory S
WHERE I.item_no = S.item_no
);
因为使用exists 查询时不会进行排序,而且使用exists和使用连接效率一样高。
总结
本文讨论了SQL中避免出现无谓的排序,通过两个示例进行说明,尽量使用union all 代替 union,exists 代替 distinct。