【SQL】其它查询优化策略
- exists和in
- count(*) count(1) count(具体字段)
- select (*)
- limit 1
- 多使用commit
exists和in
小表驱动大表
select * from A where cc in (select cc from B);
select * from A where exists (select cc from B where B.cc = A.cc);
当A表小于B表时,用exists,相当于从外层输入数据到内层,循环的次数取决于外层的数据个数。
当B表小于A表时,用in,相当于提前给A表划定范围。
count(*) count(1) count(具体字段)
count(1) 和 count(*) 本质上没有区别,执行效率可以看成是相等的。
使用myISAM存储引擎,统计数据表的行数只需要O(1)的复杂度,因为MyISAM存储了记录的总数;
如果是InnoDB存储引擎,则是全表扫描,复杂度O(n),通过循环+计数方式完成。
采用count(具体字段)来统计数据行数,尽量用二级索引字段而不是主键索引,因为主键是聚簇索引,扫描时会将所有数据加载到内存中,而二级索引中数据少,加载的成本更低。
select (*)
尽量不要使用select (*),用到哪个字段直接写上。
① MySQL 在解析的过程中,会通过查询数据字典将" *"按序转换成所有列名,这会大大的耗费资源和时间。
② 无法使用覆盖索引
limit 1
针对的是会扫描全表的 SQL 语句,如果你可以确定结果集只有一条,那么加上LIMIT 1 的时候,当找到一条结果的时候就不会继续扫描了,这样会加快查询速度。
如果数据表已经对字段建立了唯一索引,那么可以通过索引进行查询,不会全表扫描的话,就不需要加上LIMIT 1 了。
多使用commit
只要有可能,在程序中尽量多使用 COMMIT,这样程序的性能得到提高,需求也会因为 COMMIT 所释放的资源而减少。
COMMIT 所释放的资源:
- 回滚段上用于恢复数据的信息
- 被程序语句获得的锁
- redo / undo log buffer 中的空间
- 管理上述 3 种资源中的内部花费