1、MySQL 查询统计数据表行数三种方式:select count(*) 、select count(1) 、select count(具体字段),三者查询效率是怎么样的呢?
解答:
在MySQL InnoDB 存储引擎中,count(*) 和count(*) 都是对所有结果进行count。如果有where 子句,则是对所有筛选条件的数据行进行统计;如果没有where子句,则是对数据表的数据行数进行统计。
因此count(*) 和 count(1) 本质上并没有区别,执行的复杂度都是O(N),也就是采用全表扫描,进行循环+计数的方式进行统计。
如果是MySQL MyISAM 存储引擎,统计数据表的行数只需要O(1)的复杂度,这是因为每张MyISAM的数据表都有一个meta信息存储了row_count值,而一致性则由表级锁来保证,因为InnoDB支持事务,采用行级锁和MVCC机制,所以无法像MyISAM一样,只维护一个row_count变量,因此采用扫描全表,进行循环+计数的方式来完成统计;
在执行过程中,count(*) 和 count(1)执行时间略有差别,不过效率可以基本看成是相等的。
一般情况,三者的执行效率count(1) = count(*) >count(字段)。我们尽量使用count(*),当然如果你知道你要统计的是某个字段的非空数据行数,则另当别论,毕竟比较执行效率的前提是结果一样才可以。
如果统计count(*),尽量在数据表上建立二级索引,系统会自动采用key_len小的二级索引,这样当我们使用select count(*) 的时候效率会提升。
2、limit 关键词是最后执行的,如果只有一条结果,limit 还有用吗?
解答:
如果你确认结果集只有一条,加上limit 1,当找到一条结果的时候就不会继续扫描了,这样会加快查询速度,这里指的查询优化针对的是会扫描全表的sql语句,如果数据表已经对字段建立了唯一索引,那么可以通过索引进行查询,不会全表扫描的话,就不需要加limit了。
3、可以理解在where 条件字段上加索引,但是为什么在order by 字段上还要加索引呢?这个时候已经通过where条件过滤得到了数据,已经不需要再筛选过滤数据了,只需要根据字段排序就好了。
解答:
在MySQL中支持两种排序方式,分别是FileSort 和 Index 排序。在Index中,索引可以保证数据的有序性,不需要再进行排序,效率更高。filesort 排序则一般再内存中进行排序,占用cpu较多,如果待排结果较大,会产生临时文件I/O到磁盘进行排序的情况,效率较低。
所以使用Order by 子句时,应该尽量使用Index 排序,避免使用File Sort排序,当然你可以使用explain 来查看执行计划。
优化建议:
1)SQL中,可以在where 子句和order by 子句中使用索引,目的在where子句中避免全表扫描,在order by子句避免使用File sort排序,当然某些情况下全表扫描,或者filesort排序不一定比索引慢。
2)尽量使用index 完成order by排序,如果where 和order by 后面是相同的列就使用单列索引,不是则使用联合索引。
3)无法使用index 时,需要对filesort方式进行调优。
4、order by 是对分的组排序还是对分组中的记录排序呢?
解答:
order by 就是对记录进行排序,如果你在order by 前面用了group by,实际上这是一种分组的聚合方式,已经把一组的数据聚合成为了一条记录,再进行排序的时候,相对于对分的组进行了排序。
5、一条完整的select 语句内部的执行顺序是这样的:
1、from 子句组装数据(包括通过on进行连接);
2、where 子句进行条件筛选;
3、group by 分组;
4、使用聚合函数进行计算;
5、having 筛选分组;
6、计算所有的表达式;
7、select 的字段;
8、order by 排序;
9、limit 筛选。
6、不太理解哪种情况下应该使用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。因为 EXISTS 的实现,相当于外表循环,实现的逻辑类似于:
for i in A for j in B if j.cc == i.cc then ...
当B<A时,用in,因为实现的逻辑类似于:
for i in B for j in A if j.cc == i.cc then
哪个表小就用哪个表来驱动,A表小就用exists,B表小就用in
来源:https://www.cnblogs.com/Camiluo/p/11679126.html