关于 EXISTS , 更多详情可查看:神奇的 SQL 之谓词 → 难理解的 EXISTS
使用连接代替 IN其实在平时工作当中 , 更多的是用连接代替 IN 来改善查询性能 , 而非 EXISTS , 不是说连接更好 , 而是 EXISTS 很难掌握
回到问题:查询有充值记录的顾客信息 , 如果用连接来实现 , SQL 改如何写?

文章插图
这种写法能充分利用索引;而且 , 因为没有了子查询 , 所以数据库也不会生成中间表;所以 , 查询效率是不错的
至于 JOIN 与 EXISTS 相比哪个性能更好 , 不太好说;如果没有索引 , 可能 EXISTS 会略胜一筹 , 有索引的话 , 两者差不多
避免排序说到 SQL 的排序 , 我们第一时间想到的肯定是: ORDER BY , 通过它 , 我们可以按指定的某些列来顺序输出结果
但是 , 除了 ORDER BY 显示的排序 , 数据库内部还有很多运算在暗中进行排序;会进行排序的代表性的运算有下面这些

文章插图
如果只在内存中进行排序 , 那么还好;但是如果因内存不足而需要在硬盘上排序 , 那么性能就会急剧下降
因此 , 尽量避免(或减少)无谓的排序 , 能够大大提高查询效率
灵活使用集合运算符的 ALL 可选项SQL 中有 UNION 、 INTERSECT 、 EXCEPT 三个集合运算符 , 分表代表这集合运算的 并集、交集、差集
默认情况下 , 这些运算符会为了排除掉重复数据而进行排序

文章插图
Using temporary 表示进行了排序或分组 , 显然这个 SQL 没有进行分组 , 而是进行了排序运算
如果我们不在乎结果中是否有重复数据 , 或者事先知道不会有重复数据 , 可以使用 UNION ALL 代替 UNION

文章插图
可以看到 , 执行计划中没有排序运算了
对于 INTERSECT 和 EXCEPT 也是一样的 , 加上 ALL 可选项后就不会进行排序了
加上 ALL 可选项是一个非常有效的优化手段 , 但各个数据库对它的实现情况却是参差不齐 , 如下图所示

文章插图
注意:Oracle 使用 MINUS 代替 EXCEPT ;MySQL 压根就没有实现 INTERSECT 和 EXCEPT 运算
使用 EXISTS 代替 DISTINCT为了排除重复数据 , DISTINCT 也会进行排序
还记得用连接代替 IN 的案例吗 , 如果不用 DISTINCT
SQL: SELECT tc.* FROM tbl_recharge_record trr LEFT JOIN tbl_customer tc on trr.customer_id = tc.id
那么查出来的结果会有很多重复记录 , 我们改进 SQL
SELECT DISTINCT tc.* FROM tbl_recharge_record trr LEFT JOIN tbl_customer tc on trr.customer_id = tc.id
会发现执行计划中有个 Using temporary , 表示用到了排序运算

文章插图
我们使用 EXISTS 来进行优化

文章插图
可以看到 , 已经规避了排序运算
在极值函数中使用索引SQL 语言里有两个极值函数: MAX 和 MIN , 使用这两个函数时都会进行排序
例如: SELECT MAX(recharge_amount) FROM tbl_recharge_record
会进行全表扫描 , 并会进行隐式的排序 , 找出单笔充值最大的金额
但是如果参数字段上建有索引 , 则只需要扫描索引 , 不需要扫描整张表
例如: SELECT MAX(customer_id) FROM tbl_recharge_record;
会通过索引: idx_c_id 进行扫描 , 找出充值记录中最大的顾客ID
这种方法并不是去掉了排序这一过程 , 而是优化了排序前的查找速度 , 从而减弱排序对整体性能的影响
推荐阅读
- 视频短片是怎样拍摄制作出来的?需要怎样的流程?
- 用 Loki 和 fzf 进阶你的 Shell 历史记录
- 为什么隋唐演义中有罗成,又有罗士信 历史上的罗士信是傻子吗
- 桃花源记是陶渊明想象的吗 陶渊明在桃花源记中表现桃花源人什么
- 雍正对李卫有多信任 李卫是雍正的什么人
- 第二次鸦片战争的爆发有何关联 第二次鸦片战争的爆发时间
- 明朝被李自成打败的还是清朝打败的 李自成与清军大战为何大败
- 六堡茶祛湿效果怎么样,六堡茶的功效介绍
- 庐山云雾的特点先容,庐山云雾作用及功效介绍
- 百合花花茶的功效,百合花茶百合花茶的作用和功效
