数据库 | SQL语法优化方法及实例详解
使用复合索引
如果经常执行如上查询,那么建立三个单独索引不如建立一个复合索引,因为三个单独索引通常数据库每次执行只能使用其中一个,虽然这样比不使用索引而进行全表扫描提高了很多效率,但使用复合索引因为索引本身就对应到三个字段上的,效率会有更大提升。
那么为什么数据库只支持一条查询语句只使用一个索引?简单的讲是因为N个独立索引同时在一条语句使用的效果比只使用一个索引还要慢,开销太大。
在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
同时,复合索引的也是有生效原则的,其原则是从前往后依次使用则生效,如果中间某个索引没有使用,那么“断点”前面的索引生效,断点后面的索引不生效,造成“断点”的原因一般有:
- 前边的任意一个索引没有参与查询,后面的不生效。
- 前边的任意一个索引失效,当前索引及后面的不生效。
- 前边的任意一个索引字段参与的是范围查询,后面的不生效。
引发索引失效,导致全表扫描的原因有:
- 索引列进行计算、函数、类型转换等操作。
- 索引列使用不等于,如!= 或<>。
- 索引列使用 IS NULL ,IS NOT NULL。
- 模糊查询LIKE 以通配符开头如,%ab。
- 索引列使用使用 OR 来连接条件。
- 索引列使用IN 和 NOT IN 。
- 类型错误,如字段NUM类型为varchar,WHERE条件用number,NUM = 1。
- WHERE子句和ORDER BY使用相同的索引,并且ORDER BY的顺序和索引顺序相同,并且ORDER BY的字段都是升序或者降序,否则不会使用索引。
- 复合索引不符合最佳左前缀原则或存在断点。
- 如果MYSQL评估使用索引比全表扫描更慢,则不使用索引。
例如我们建立了一个这样复合索引key index (col1,col2,col3),那么其实相当于创建了(col1),(col1,col2),(col1,col2,col3)三个索引,即最佳左前缀特性。
索引失效的优化技巧
应尽量避免在 WHERE 子句中使用 != 或 <> 操作符,否则将导致引擎放弃使用索引而进行全表扫描。MySQL只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些方式的LIKE('a%'),如下。
WHERE 子句中使用 LIKE进行模糊查询时,在关键词前加通配符或者前后都加通配号都无法使用索引,从而引发全表扫描。解决LIKE '%abc%' 时索引不被使用的方法就是添加覆盖索引(只访问索引的查询,索引和查询列一致,只需扫描索引而无须回表),如下。
应尽量避免在 WHERE 子句中对字段进行 NULL 值判断,否则将导致引擎放弃使用索引而进行全表扫描,创建表时NULL是默认值,但大多数时候应该使用NOT NULL,或者使用一个默认值,如 0 作为默认值。
例如,性别,使用1表示男,2表示女,0表示未知或者是用户没有选择,默认值设置为 0,因为大部分编程语言的数字类型的默认值0,如下。
空值和NULL是有区别的,以一个杯子为例:
- 空值代表杯子是真空的。
- NULL代表杯子中装满了空气。
如果字段允许为空,可能会有以下问题:
- 查询条件就必须处理为空的情况,否则会出现一些很奇怪的问题,比如NOT IN、!= 等负向条件查询在有 NULL 值的情况下返回始终为空结果,查询易出错。
- 在部分数据库中会导致索引失效。
- 可空列需要更多的存储空间,导致空间变大,增加数据库系统查询分析复杂度。
- 在程序中可能需要每次都判断是否为空,增加程序复杂复杂度。
但凡事没有绝对的,使用默认值的思路可以解决很大一部分可为空的问题,但不是所有都需这样做,具体还是要根据具体业务进行分析。
应尽量避免在 WHERE 子句中使用 OR 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。使用 OR 的字句可以分解成多个查询,并且通过UNION 连接多个查询。他们的速度只同是否使用索引有关,如果查询需要用到联合索引,用UNION ALL执行的效率更高,如下。
应尽量避免在 WHERE 子句中使用 IN 和 NOT IN ,否则将导致全表扫描,对于连续的数值,能用 BETWEEN AND 尽量避免使用 IN。一般,用 EXISTS 代替 IN 。若需要使用 IN,在 IN 后面值的列表中,按照值的分布数量降序排列,减少判断的次数。
使用BETWEEN AND 替换 IN ,如下。
使用EXISTS 替代IN,用NOT EXISTS 替代 NOT IN,无论在哪种情况下, NOT IN效率都是最低的,如下。
使用LEFT JOIN 替换 IN,如下。
如上,我们使用了如下方式优化了IN 和 NOT IN:
- 使用between 替换 in ( 如果 in 的条件是连续的)
- 使用exists替代in、用not exists替代 not in
- 使用left join 替换 in
应尽量避免在 WHERE 子句中对 “=” 左边的字段进行函数、算术运算及其他表达式运算,可以将表达式运算移至“=”右边,否则将导致引擎放弃使用索引而进行全表扫描,如下。
如果在 WHERE 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时。它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项,可以改为强制查询使用索引,如下。
LIMIT 分页优化
在分页查询偏移量特别大时,LIMIT 效率会相当低,如下。
数据删除优化
存在如下表,n_id是主键,id_card是人员编码,数字类型,表中id_card有重复,已经建了id_card索引,如下。
用EXISTS替换DISTINCT
EXISTS语句用来判断括号内的表达式是否存在返回值,如果存在就返回真,如果不存在就返回假,同时它只要括号中的表达式有一个值存在,就立刻返回真,而不需要遍历表中所有的数据,正是因此 EXISTS 使查询效率更高,如下。
数据库 | SQL语法优化方法及实例详解的更多相关文章
- jQuery中on()方法用法实例详解
这篇文章主要介绍了jQuery中on()方法用法,实例分析了on()方法的功能及各种常见的使用技巧,并对比分析了与bind(),live(),delegate()等方法的区别,需要的朋友可以参考下 本 ...
- 数据库sql常见优化方法
以前刚开始做项目的时候,开发经验尚浅,每次遇到查询比较慢时,项目经理就会问:是不是又用select * 了?查询条件有没有加索引?一语惊醒梦中人,赶紧检查..果然如此! 有时我们写sql语句时,没有考 ...
- nginx配置:location配置方法及实例详解
今天深入研究了下nginx的location的用法,已经一些需要注意的细节,现在做一个归纳总结,以备后面查询. location匹配的是nginx的哪个变量? $request_uri locatio ...
- 【转】nginx配置:location配置方法及实例详解
location匹配的是nginx的哪个变量? $request_uri location的匹配种类有哪些? 格式 location [ 空格 | = | ~ | ~* | !~ | !~* ] /u ...
- 【转】【Centos】nginx配置:location配置方法及实例详解
location匹配的是nginx的哪个变量? $request_uri location的匹配种类有哪些? 格式 location [ 空格 | = | ~ | ~* |^~ | !~ | !~* ...
- C#操作SQLite方法实例详解
用 C# 访问 SQLite 入门(1) CC++C#SQLiteFirefox 用 C# 访问 SQLite 入门 (1) SQLite 在 VS C# 环境下的开发,网上已经有很多教程.我也是从 ...
- Linux备份数据库,mysqldump命令实例详解
mysqldump是mysql数据库中备份工具,用于将MYSQL服务器中的数据库以标准的sql语言的方式导出,并保存到文件中. 语法: mysqldump (选项) 选项: --add-drop-ta ...
- mysql数据库分区功能及实例详解
分区听起来怎么感觉是硬盘呀,对没错除了硬盘可以分区数据库现在也支持分区了,分区可以解决大数据量的处理问题,下面一起来看一个mysql数据库分区功能及实例详解 一,什么是数据库分区 前段时间写过一篇 ...
- 这个贴子的内容值得好好学习--实例详解Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化
感觉要DJANGO用得好,ORM必须要学好,不管理是内置的,还是第三方的ORM. 最最后还是要到SQL.....:( 这一关,慢慢练啦.. 实例详解Django的 select_related 和 p ...
随机推荐
- 解决No module named 'sklearn.cross_validation'
sklearn中已经废弃cross_validation,将其中的内容整合到model_selection中 将sklearn.cross_validation 替换为 sklearn.model_s ...
- 阿里云服务执行mysql_install_db报错
问题描述:阿里云服务执行mysql_install_db报错解决方案:安装autoconf库(yum -y install autoconf)然后在执行:mysql_install_db就会出现这样, ...
- 【2017-06-16】Jquery获取dropdownlist选中的内容
var Text = $("#DropDownList1 option:selected").text(); 注意:DropDownList1和option之间有个空格!!!
- 03_Redis_String命令
一:Redis命令---String命令:Redis 字符串数据类型的相关命令用于管理 redis 字符串值 字符串类型是Redis中最为基础.常用的数据存储类型,字符串在Redis中是二进制安全的, ...
- vim文本编辑及文件查找应用4
linux系统上的特殊权限 : 特殊权限有:SUID,SGID,STICKY 安全上下文: 1.进程以其发起者的身份运行:进程对文件的访问权限,取决于发此进程的用户的权限:进程是发起些进程用户的代理, ...
- Python3学习笔记36-PEP8代码规范
在使用PyCharm时,最右边会有波浪线警告提示代码不符合PEP8代码规范.记录一下犯的错和解决方式 PEP8是风格错误,而不是编码错误.只是为了让代码更具有阅读性. 1)block comment ...
- C++获取文件夹下所有文件的路径
代码 getFiles()函数的作用: path是一个文件夹路径,函数在path文件夹下寻找所有文件(包括子文件夹下的文件),然后将所有文件的路径存入files #include <io.h&g ...
- CSS基础学习 20.CSS媒体查询
- Spring入门篇——第1章 概述
第1章 概述 本章对课程的情况进行介绍,并介绍框架和Spring概况. 1-1 Spring入门课程简介 1-2 Spring概况 1-3 Spring框架
- [六省联考2017]分手是祝愿——期望DP
原题戳这里 首先可以确定的是最优策略一定是从大到小开始,遇到亮的就关掉,因此我们可以\(O(nlogn)\)的预处理出初始局面需要的最小操作次数\(tot\). 然后容(hen)易(nan)发现即使加 ...