消除不必要的DISTINCT条件
- Content:太多DISTINCT条件是复杂的裹脚布式查询的症状。考虑将复杂查询分解成许多简单的查询,并减少DISTINCT条件的数量。如果主键列是列的结果集的一部分,则DISTINCT条件可能没有影响。
- Case:
SELECT DISTINCT c.c_id,count(DISTINCT c.c_name),count(DISTINCT c.c_e),count(DISTINCT c.c_n),count(DISTINCT c.c_me),c.c_d FROM (select distinct xing, name from B) as e WHERE e.country_id = c.country_id
COUNT(DISTINCT)多列时结果可能和你预想的不同
- Content:COUNT(DISTINCT col)计算该列除NULL之外的不重复行数,注意COUNT(DISTINCT col, col2)如果其中一列全为NULL那么即使另一列有不同的值,也返回0。
- Case:
SELECT COUNT(DISTINCT col, col2) FROM tbl;
DISTINCT *对有主键的表没有意义
- Content:当表已经有主键时,对所有列进行DISTINCT的输出结果与不进行DISTINCT操作的结果相同,请不要画蛇添足。
- Case:
SELECT DISTINCT * FROM film;
避免在WHERE条件中使用函数或其他运算符
- Content:虽然在SQL中使用函数可以简化很多复杂的查询,但使用了函数的查询无法利用表中已经建立的索引,该查询将会是全表扫描,性能较差。通常建议将列名写在比较运算符左侧,将查询过滤条件放在比较运算符右侧。
- Case:
select id from t where substring(name,1,3)='abc'
指定了WHERE条件或非MyISAM引擎时使用COUNT(*)操作性能不佳
- Content:COUNT(*)的作用是统计表行数,COUNT(COL)的作用是统计指定列非NULL的行数。MyISAM表对于COUNT(*)统计全表行数进行了特殊的优化,通常情况下非常快。但对于非MyISAM表或指定了某些WHERE条件,COUNT(*)操作需要扫描大量的行才能获取精确的结果,性能也因此不佳。有时候某些业务场景并不需要完全精确的COUNT值,此时可以用近似值来代替。EXPLAIN出来的优化器估算的行数就是一个不错的近似值,执行EXPLAIN并不需要真正去执行查询,所以成本很低。
- Case:
SELECT c3, COUNT(*) AS accounts FROM tab where c2 < 10000 GROUP BY c3 ORDER BY num
使用了合并为可空列的字符串连接
- Content:在一些查询请求中,您需要强制让某一列或者某个表达式返回非NULL的值,从而让查询逻辑变得更简单,担忧不想将这个值存下来。使用COALESCE()函数来构造连接的表达式,这样即使是空值列也不会使整表达式变为NULL。
- Case:
select c1 || coalesce(' ' || c2 || ' ', ' ') || c3 as c from tbl
不建议使用SYSDATE()函数
- Content:SYSDATE()函数可能导致主从数据不一致,请使用NOW()函数替代SYSDATE()。
- Case:
SELECT SYSDATE();
不建议使用COUNT(col)或COUNT(常量)
- Content:不要使用COUNT(col)或COUNT(常量)来替代COUNT(*),COUNT(*)是SQL92定义的标准统计行数的方法,跟数据无关,跟NULL和非NULL也无关。
- Case:
SELECT COUNT(1) FROM tbl;
使用SUM(COL)时需注意NPE问题
- Content:当某一列的值全是NULL时,COUNT(COL)的返回结果为0,但SUM(COL)的返回结果为NULL,因此使用SUM()时需注意NPE问题。可以使用如下方式来避免SUM的NPE问题: SELECT IF(ISNULL(SUM(COL)), 0, SUM(COL)) FROM tbl
- Case:
SELECT SUM(COL) FROM tbl;