<<SQL进阶教程>>([日]MICK/著 吴炎昌/译)之性能优化篇

一:使用高效的查询
1.参数是子查询时,使用EXISTS代替IN;
如果参数是"1,2,3"这样的数值列表,一般不需要特别注意。
使用EXISTS时更快的原因有以下2个:
1.1如果连接列(id)上建立了索引,那么查询里面表时不要查实际的表,只需查索引就可以了。
1.2如果使用EXISTS,那么只要查到一行数据满足条件就会终止查询,不要像使用IN时一样扫描全表。在这一点上NOT EXISTS也一样。
当IN的参数是子查询时,数据库首先执行子查询,然后将结果存储在一张临时的工作表里(内联视图),然后扫描整个视图,耗费资源,EXISTS不会。
2.参数是子查询时,使用连接代替IN;
可用到索引,如果没有索引,那么与连接相比,可能EXISTS会更快。
二:避免排序
在数据库内部频繁地进行着暗中的排序的运算有下面这些。
GROUP BY 子句
ORDER BY 子句
聚合函数(SUM\COUNT\AVG\MAX\MIN)
DISTINCT
集合运算符(UNION\INTERSECT\EXCEPT(即ORACLE的MINUX))
窗口函数(RANK\ROW_NUMBER等)
内存不足的话需要在硬盘上排序(据说硬盘的访问速度比内存的要慢上100万倍)
1.灵活使用集合运算符的ALL可选项;
UNION ALL不会排序,且几乎每种数据库都支持,DB2和PostgreSQL另外2个集合运算符也支持ALL可选项。
2.使用EXISTS代替DISTINCT;
一对一和一对多时比较实用,当然优先使用EXISTS。
3.在极值函数中使用索引(MAX\MIN);
SQL语言里有MAX和MIN两个极值函数,使用这2个函数时都会进行排序。
对于联合索引,只有查询条件是联合索引的第一个字段,索引就是有效的。
这种方法并不是去掉了排序这一过程,而是优化了排序前的查找速度(扫描索引而不是扫描整张表),从而减弱排序对整体性能的影响。
4.能写在WHERE子句里的条件不要写在HAVING子句里;
使用GROUP BY子句聚合时会进行排序,如果事先通过WHERE子句筛选出一部分行,就能减轻排序的负担。
WHERE子句可以使用索引,HAVING子句是针对聚合后生成的视图进行筛选的,很多时候并无继承原表的索引结构。
5.在GROUP BY子句和ORDER BY子句中使用索引;
通过指定带索引的列作为GROUP BY和ORDER BY的列,可以实现高速查询。
三:真的用到索引了吗(索引:轻量化查询更高效)
1.在索引字段上进行运算,不会用到索引;
如col_1列建立了索引,where col_1 * 1.1 > 100;或where substr(col_1, 1, 1) = ‘a‘;
使用索引时,条件表达式的左侧应该是原始字段,这一点是优化索引时首要关注的地方。函数索引可用但少用。
2.使用IS NULL或IS NOT NULL,不用到索引,但ORACLE和DB2也能用到索引,可能因为他们实现NULL时赋了某个具有特殊含义的值;
索引字段不存在NULL,因为NULL并不是值,非值不会被包含在值的集合中。
另IS NOT NULL可用>列的最小值代替,基本可得到一样的结果,且能索引,但最准确还是IS NOT NULL,不推荐。
3.使用否定形式,不会用到索引;
下面这几种否定形式不会用到索引。
<>
!=
NOT IN
4.使用OR,不会用到索引;
在col_1和col_2上分别建立了不同的索引,或者建立了(col_1,col_2)这样的联合索引时,如果使用or连接条件,要么用不到索引,要么用
到了但是效率比AND要差很多。如where col_1 > 100 or col_2 = ‘abc‘;
可用位图索引,但这种索引更新数据时性能开销会增大,索引使用之前要权衡一下利弊。
5.使用联合索引时,列的顺序错误,不会用到索引;
联合索引中的第一列必须写在查询条件开头,而且索引中列的顺序不能颠倒(可考虑将联合索引拆分为多个索引)。
假如有这样一个联合索引“col_1,col_2,col_3”,
where col_1=10 and col_2=100;可用到;
where col_1=10 and col_3=500;无法用到;
where col_2=10 and col_3=500;无法用到;
where col_2=10 and col_1=20; 无法用到;
6.使用LIKE谓词进行后方一致或中间一致的匹配,不会用到索引;
使用LIKE谓词时,只有前方一致的匹配才能用到索引,所以where col_1 like ‘%a%‘和where col_1 like ‘%a‘都用不到索引。
7.进行默认的类型转换,不会用到索引;
如对char类型的"col_1"列指定条件查询where col_1=10不会用到索引,而where col_1=‘10‘和where col_1=cast(10,as char(2))可用到。
四:减少中间表
中间表会带来2个问题,1是展开数据需要耗费内存资源,2是原始表中的索引不容易使用到(特别是聚合时)。
1.灵活使用HAVING子句;
对聚合结果指定筛选条件时,使用HAVING子句是基本原则。不要先生成GROUP BY的中间表再在外面套一层用WHERE筛选,直接一层用HAVING筛选。
HAVING子句和聚合操作是同时执行的,索引比起生成中间表后再执行的WHERE子句,效率会更高一些,而且代码看起来更简洁。
2.需要对多个字段使用IN谓词时,将它们汇总到一处;
如SELECT id,state,city
FROM Addresses1 A1
WHERE state IN (SELECT state
FROM Addresses2 A2
WHERE A1.id = A2.id)
AND city IN (SELECT city
FROM Address2 A2
WHERE A1.id = A2.id);
可以替换成
SELECT *
FROM Addresses1 A1
WHERE id || state || city
IN (SELECT id || state || city
FROM Addresses2 A2);
有点数据库还可以这样替换,没有字段类型隐式转换,而且可以使用到索引
SELECT *
FROM Addresses1 A1
WHERE (id, state, city)
IN (SELECT id, state, city
FROM Addresses2 A2);
3.先进行连接再进行聚合;
连接表双方是一对一、一对多的关系时,连接后数据的行数不会增加,连接和聚合同时使用的话,先进行连接可以避免产生中间表。
4.合理使用视图;
视图的定义语句中包含以下运算的时候,SQL会非常低效,,执行速度也会变得非常慢。
聚合函数(AVG、COUNT、SUM、MIN、MAX)
聚合运算符(UNION、INTERSECT、EXCEPT等)
为避免这个缺点,可以使用物化视图。

原文地址:https://www.cnblogs.com/jiangqingfeng/p/12588842.html

时间: 2024-11-07 16:24:35

<<SQL进阶教程>>([日]MICK/著 吴炎昌/译)之性能优化篇的相关文章

分享《SQL进阶教程》高清中文PDF+源代码

下载:https://pan.baidu.com/s/11-MnDu0khzwO4tiJqHznnA <SQL进阶教程>高清中文PDF+源代码 下载:https://pan.baidu.com/s/1a-JepzWU77yH0IUfBiLPPw <SQL基础教程(第2版)>高清中文PDF+示例程序+习题答案 更多分享资料:https://pan.baidu.com/s/1g4hv05UZ_w92uh9NNNkCaA <SQL进阶教程>高清中文PDF+源代码+MICK (

《SQL必知必会(第4版)》中英文PDF及代码+《SQL进阶教程》中文PDF及代码 (学习总结)

下载:https://pan.baidu.com/s/1hRb-TS_R-0fnXPodS5OoDg <SQL必知必会(第4版)>高清中文PDF+高清英文PDF+代码 下载:https://pan.baidu.com/s/11-MnDu0khzwO4tiJqHznnA <SQL进阶教程>高清中文PDF+源代码 <SQL必知必会(第4版)>高清中文PDF+高清英文PDF+代码 高清中文PDF,258页,带书签目录,文字可以复制粘贴:高清英文PDF,497页,带书签目录,文

《SQL进阶教程》

例题: 注意,最后必须写上ELSE语句. 在刚开始介绍 CASE 表达式的时候我们就已经了解到,如果 CASE 表达式里没有明 确指定 ELSE 子句,执行结果会被默认地处理成 ELSE NULL .现在 大家明白笔者最开始强调使用 CASE 表达式时要习惯性地写上 ELSE 子句的理由了吧? 练习题: 去重: <SQL进阶教程> 原文地址:https://www.cnblogs.com/JasonPeng1/p/12110109.html

《SQL 进阶教程》 case:练习题1-1-3 用 ORDER BY 指定顺序进行排序

select name from greatestsORDER BY case when name ='B' then 1 when name ='A' then 2 when name ='D' then 3 when name ='C' then 4 else 5 end 原文地址:https://www.cnblogs.com/newlangwen/p/10565919.html

shell进阶教程

背景:就自己常用的shell脚本写作风格,总结了一些知识点.也是作为交接工作的一部分文档.部分内容单独写 #!/bin/sh # shell脚本进阶教程 # 1.常用知识点:变量设置/日期设置/格式化输出/定义函数/函数传参/脚步传参/变量的嵌套和迭代 # 2.常用环境:/数据库监控/本地日志监控/批量处理/定期获取表数据/备份 # 3.常用循环:for/while # 4.常用命令:sed/cut/awk/ # 5.crontab 计划任务 # 第一部分:常用知识点 # 1.[变量设置及变量替

Influx Sql系列教程二:retention policy 保存策略

retention policy这个东西相比较于传统的关系型数据库(比如mysql)而言,是一个比较新的东西,在将表之前,有必要来看一下保存策略有什么用,以及可以怎么用 I. 基本操作 1. 创建retention policy retention policy依托于database存在,也就是说保存策略创建时,需要指定具体的数据库,语法如下 CREATE RETENTION POLICY <retention_policy_name> ON <database_name> DUR

二、个人总结的菜鸟教程|sql教程的知识点(SQL高级教程)

二.SQL高级教程 1.SQL SELECT TOP SELECT TOP 子句用于规定要返回的记录的数目. SELECT TOP 子句对于拥有数千条记录的大型表来说,是非常有用的. 注释:并非所有的数据库系统都支持 SELECT TOP 子句. sql server|ms access语法 select top number|percent column_name from table_name; mysql|oracle语法(与top等价) select Column_name from t

Nodejs爬虫进阶教程之异步并发控制

Nodejs爬虫进阶教程之异步并发控制 之前写了个现在看来很不完美的小爬虫,很多地方没有处理好,比如说在知乎点开一个问题的时候,它的所有回答并不是全部加载好了的,当你拉到回答的尾部时,点击加载更多,回答才会再加载一部分,所以说如果直接发送一个问题的请求链接,取得的页面是不完整的.还有就是我们通过发送链接下载图片的时候,是一张一张来下的,如果图片数量太多的话,真的是下到你睡完觉它还在下,而且我们用nodejs写的爬虫,却竟然没有用到nodejs最牛逼的异步并发的特性,太浪费了啊. 思路 这次的的爬

duilib进阶教程 -- 响应windows原生消息和自定义消息(13)

duilib进阶教程 -- 响应windows原生消息和自定义消息(13) 一.windows原生消息 同样,入门教程只是给出了响应windows原生消息的方法,并没给出例子,这里以自适应屏幕分辨率为例.迅雷播放器虽然可以在启动的时候自动调整窗口大小,但是当屏幕分辨率实时改变时并没有调整窗口,所以我们给播放器加上实时调整大小的功能,很明显,应该响应WM_DISPLAYCHANGE消息,而duilib自己处理windows消息的函数是在HandleMessage里,因此我们重载HandleMess