“SQL性能优化是一种黑魔法
就像炼金术一样:
各种配方难解晦涩,
只有一小部分圈内人才能理解。”
这是一种误解,SQL数据库使用的是大家公知的算法来实现可以预期的执行性能。然而,问题是,人们很容易写出不能发挥最高效算法的SQL查询语句,因而也容易产生无法预期的性能结果。
下面是5个关于SQL性能优化的demo,这些demo也许会让你坚信SQL优化就是一种黑魔法。但答案中提供的解释说明会随即让你明白,这些所谓的黑魔法其实是纯粹的科学。
本demo中使用的SQL是基于Oracle数据库。
1.
查询出年是2012的所有行:
CREATE INDEX tb1_idx ON tb1 (date_column);
SELECT text, date_column
FROM tb1
WHERE TO_CHAR(date_column,'YYYY') = '2012';
这样写会有重大的性能问题, 当表字段放到函数里执行查询时,索引将不起作用,效率更高的写法如下:
SELECT text, date_column
FROM tb1
WHERE date_column >= TO_DATE('2012-01-01','YYYY-MM-DD'
AND date_column < TO_DATE('2013-01-01','YYYY-MM-DD');
2.
查询一个字符串:
CREATE INDEX tb1_idx ON tb1(text);
SELECT id, text
FROM tb1
WHERE text LIKE '%TERM%'
这样写可能会产生重大的性能问题, 因为like对应的查询字符如果是以通配符开头的,索引将无法发挥效能。也没有一个简单的方法来优化这种SQL
3.
如果从百万行数据中查询出几千行时,我们使用:
CREATE INDEX tab_idx ON tb1 (a, date_column);
SELECT date_column, count(*)
FROM tb1
WHERE a = ?
GROUP BY date_column;
而当我们只需要从百万航数据中查询出10行时, 把SQL改成这样:
SELECT date_column, count(*)
FROM tb1
WHERE a = ?
AND b = ?
GROUP BY date_column;
修改后SQL执行效率至少会慢10%左右. 在前一种查询中,索引覆盖了所有的查询字段,执行效能会非常高,而修改后的SQL,虽然返回的数据变少了,但新增的B字段并没有索引。
4.
查询num为null的ID>:
SELECT id
FROM tb1
WHERE num is null
应避免使用!=或<>、IS NULL或IS NOT NULL、IN ,NOT IN等这样的操作符,因为这会使系统无法使用索引,而只能直接搜索表中的数据。
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
SELECT id
FROM tb1
WHERE num = 0
其他的优化查询的方式还有很多, 例如in和not尽量应用exists和not exists取代; 能用union all尽量不要用union; 能够用between就不要用in ; 能用数值型的字段不要用varchar ; 利用建视图的方式来加速查询等等..有空再细说吧..