SQL 语句优化及编程方法

embedded/2024/11/20 11:09:11/

DBMS生成的执行计划在很大程度上要受到代码外部结构的影响。因此要想优化查询性能,就必须要知道如何写代码才能使优化器的执行效率更高。

但是,不能为了“效率”牺牲代码的可读性,要让代码清晰。

1 查询优化

在解决SQL造成的性能问题时,我们还需要查看DBMS选择的执行计划来做判断。注意,优化SQL的方法未必能解决所有的性能问题。

1.1 参数是子查询

1 使用EXISTS代替IN。

  1. IN 会扫描全表,并会生成中间临时表。而EXISTS,只要查到一行数据满足条件就会终止查询。
  2. EXISTS会使用索引,而IN查询生成的中间表(铺展开来还会占用内存),很难继承原表的索引。

2 使用连接代替IN。

不一定比EXISTS效率更好,但是与IN相比,更大可能用上索引,同时也不会生成中间表。

1.2 避免排序

会进行排序的具有代表性的运算有:

  1. GROUP BY 子句。
  2. ORDER BY 子句。
  3. 聚合函数(SUM、COUNT、AVG、MAX、MIN)。
  4. DISTINCT。
  5. 集合运算符(UNION、INTERSECT、EXCEPT)。
  6. 窗口函数(RANK、ROW_NUMBER等)。

1.2.1 避免排序的诀窍

1 灵活使用集合运算符的ALL可选项。

集合运算符不加ALL,则会去除重复数据及排序。加上ALL后则不会排序及去除重复数据,例如 UNION ALL。

2 使用EXISTS代替DISTINCT。

1.3 索引

索引能极大的提高查询速度,要善用索引。

1 善用索引。

在极值函数中使用索引。在GROUP BY 和 ORDER BY中使用索引。

2 避免在索引字段上进行运算。

使用索引时,列应该是原始字段。

SELECT  *  FROM t_num WHERE num * 2 > 5; // 这样并不会使用num的索引

SELECT  *  FROM t_num WHERE num > 5 * 2; // 这样会使用num的索引。

3 尽量减少NULL值出现在索引字段中。

IS NULL 和 IS NOT NULL 查询时,索引无法使用。 NULL很多的字段也无法使用索引。

4 否定形式可能用不到索引。

例如 != 及 NOT IN 等,将会使索引失效。

5 使用OR的索引效果不佳。

6 使用联合索引时,查询字段的顺序很重要。

联合索引中的第一列必须写在查询条件的开头。查询字段的顺序最好与索引中的顺序一致。

7 使用LIKE时,只有前方一致的匹配才能用到索引。

例如 “a%”,而像”%a”则会使索引失效。

8 默认的类型转换会使索引失效。

默认的类型转换不仅会增加额外的性能开销,还会导致索引不可用。

在需要类型转换时显式地进行类型转换(转换要写在值的一边,而不是列的一边)。

例如 下面 col_1 字段类型为varchar(10)

SELECT * FROM t_str WHERE col_1 = 10; // 会执行隐性转换,索引失效

SELECT * FROM t_str WHERE col_1 = ‘10’;// 不会隐性转换,索引有效

SELECT * FROM t_str WHERE col_1 = CAST(10,AS CHAR(5)); // 显式转换,索引有效.

9 减少中间表。

频繁使用中间表会带来两个问题:1)展开数据需要消耗内存资源。2)原始表中的索引不容易被用到(特别是聚合函数)。

1.4 其他

1 筛选条件能在WHERE写就不要在HAVING写。

  1. where 先筛选能减轻排序的负担。
  2. where 可以使用索引,having是针对聚合后生成的视图进行筛选的,但是很多时候,聚合后的视图并没用基础原表的索引结构。

2 合理使用视图,避免在视图中进行聚合操作。

3 先连接再进行聚合。

可以避免产生中间表。

4 需要对多个字段使用IN谓词时,先将它们汇总到一处。

SELECT *
FROM t_address
WHERE city IN (SELECT city FROM t_address2)
AND area IN (SELECT area FROM t_address2);

上面的代码可以将多个IN合并为一个。

SELECT *
FROM t_address
WHERE (area,city) IN (SELECT area,city FROM t_address2);

这样,子查询就只要执行一次就可以了。

2 编程方法

“未来的自己,陌生如他人”,好的编程风格可以提高系统开发效率。

1 去除关联子查询。

使用窗口函数来代替关联子查询,可以提高可读性和性能。

关联子查询不容易编写,调试起来也很困难,因为关联子查询无法单独执行。

2 从FROM子句开始写。

SQL执行顺序:FROM -> WHERE -> GROUP BY -> HAVING -> SELECT (-> ORDER BY)。严格来说,ORDER BY并不是SQL语句的一部分。


http://www.ppmy.cn/embedded/139058.html

相关文章

Redis面试篇笔记(持续更新)

一、redis主从集群 单节点redis的并发能力是由上限的,要进一步提高redis的并发能力可以搭建主从集群,实现读写分离,一主多从,主节点写数据,从节点读数据 部署redis主从节点的docker-compose文件命令解析 version: &q…

基于单片机的厂房防火报警系统

本设计基于单片机的厂房防火报警系统,选用STC89C52RC作为核心的控制芯片,并且使用GSM技术来控制各种传感器,来实现多功能、多方面的安全监测。其中传感器主要包括:烟雾传感器、火焰传感器和温度传感器。主控芯片与这些传感器&…

【软件工程】一篇入门UML建模图(类图)

🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀软件开发必练内功_十二月的猫的博客-CSDN博客 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前…

【PGCCC】PostgreSQL 数据库设计中的文本标识符 | 翻译

无论是设计独立应用程序还是微服务,您都不可避免地会遇到共享标识符的话题。无论是网页的 URL、RESTful API 资源、JSON 文档、CSV 导出还是其他内容,特定资源的标识符都会被暴露。 /orders/123 /products/345/variants/1虽然标识符只是一个数字&#x…

STM32电机运动控制与直线插补算法原理讲解

1.概念 不管是做自动化设备还是机器人运动学,都离不开对电机的控制,根据实际场景有各种各样的运动控制算法,而直线运动就是其中一种控制方式,今天就跟大家分享一个直线插补运动算法的原理,而代码的实现,则…

以Java为例,实现一个简单的命令行图书管理系统,包括添加图书、删除图书、查找图书等功能。

江河湖海中的代码之旅:打造你的命令行图书管理系统 一、系统简介 1. Java简介 Java,这个编程语言界的“瑞士军刀”,自1995年诞生以来就以其跨平台的特性和强大的生态系统征服了无数开发者的心。想象一下,Java就像是一条蜿蜒曲折…

移远通信5G RedCap模组RG255C-CN通过中国电信5G Inside终端生态认证

近日,移远通信5G RedCap模组RG255C-CN荣获中国电信颁发的5G Inside终端生态认证证书。这表明,该产品在5G基本性能、网络兼容性、安全特性等方面已经过严格评测且表现优异,将进一步加速推动5G行业终端规模化应用。 中国电信5G Inside终端生态认…

【Cesium】自定义材质,添加带有方向的滚动路线

【Cesium】自定义材质,添加带有方向的滚动路线 🍖 前言🎶一、实现过程✨二、代码展示🏀三、运行结果🏆四、知识点提示 🍖 前言 【Cesium】自定义材质,添加带有方向的滚动路线 🎶一、…