前情提要 : 需求就是一个普通的两个表连接从而查询出详细信息。其中a表是大表, 测试数据都有数万条; b表是小表大概1000多条数据。
1. 为了赶工写出的未优化SQL(为突出主题, 返回字段用 * 代替不写出详细字段, WHERE条件也去掉了):
SELECT
*
FROM
A a
LEFT JOIN
B b
ON
a.JOB_ID = b.ID耗时:3.712s

rows字段代表这个步骤相对上一步结果每一行需要扫描的行数,可以看到这个sql需要扫描的行数为22711*1230, 这几乎是两个表做笛卡尔积的开销了(select * from a, b)。
MySQL对JOIN的处理采用了一种叫做BLOCK Nested-Loop 的算法。 Block Nested-Loop 算法是通过驱动表(可以简单理解为前面的表)的结果集作为循环基础数据, 然后一条一条的通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果。 如果还有第三个参与 JOIN, 则再通过前面两个表的 JOIN 结果集作为JOIN的基础数据,再一次通过循环查询条件到第三个表中查询数据。 结论: 驱动表(前面表)的数据量决定了总扫描数。
2. 从业务上
都是全表扫描, 然后我发现左表数据在业务上如果右表为NULL就没意义了, 然后改为INNER JOIN。
耗时: 2.745s

3. 可以看到上面的type都是ALL
启科网络商城系统由启科网络技术开发团队完全自主开发,使用国内最流行高效的PHP程序语言,并用小巧的MySql作为数据库服务器,并且使用Smarty引擎来分离网站程序与前端设计代码,让建立的网站可以自由制作个性化的页面。 系统使用标签作为数据调用格式,网站前台开发人员只要简单学习系统标签功能和使用方法,将标签设置在制作的HTML模板中进行对网站数据、内容、信息等的调用,即可建设出美观、个性的网站。
0
system/const/eq_ref/ref/range/index/ALL ---- 从左到右效率递减
都是type都是ALL考虑到连接的条件是否可以为主键, 有主键的话MySQL可以使用索引查询, 效率会提升很多。
由于A表是历史表做链接的字段不是主键, 所以只能在B表把这个字段加上主键。
耗时: 2.672s

还是很慢, 因为还没建立索引, 现在对B表ID字段加上索引, 结果如下:
耗时:0.109s

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号