SQL是作为一个程序员接触得非常多的一种语言,但是,很多时候,我们会发现,有些SQL的执行效率异常的差,造成了数据库的负担。我们通过分析这些有问题的SQL,就可以发现很多我们平时在写SQL的时候忽略的问题。

今天,我们就来讲一下这些需要改掉的坏习惯。

尽量少用负向条件查询

假设我们有一个Order表,表中有一个字段是Status,这个字段有4个值,分别是0=待支付、1=待发货、2=待收货、3=已完成。

这时,我们要查询所有已经支付的订单,很多人就会写这样的SQL:

select * from Order where Status != 0

这就是一个不好的习惯了。负向条件查询(例如:!=、not in、not exists)都是不能使用索引的,当Order表中的数据到达一定量级时,这个查询的效率会急剧的下降。

所以,正确的写法应该是:

select * from Order where Status in (1,2,3)

尽量少用前导模糊查询

假设我们现在要根据用户的订单号(OrderNo)查询用户的订单,如果是直接通过SQL查询的话,尽量不要使用前导模糊查询,也就是:

select * from Order where OrderNo like '%param'

或者

select * from Order where OrderNo like '%param%'

因为,前导模糊查询是无法命中索引的,所以,会整个数据库去检索,效率相当的差,而非前导模糊查询则是可以使用索引的。

因此,我们尽量不要把通配符放在前面,改成下面这样:

select * from Order where OrderNo like 'param%'

尽量不要在条件字段上进行运算

假设,现在有一个需求,是要查询2018年全年的订单数据,我们就需要通过创建时间(CreateTime)来进行检索,但是,有些程序员就喜欢这样写SQL:

select * from Order where Year(CreateTime)=2018

然后,每次执行时就会发现,查询的速度异常的慢,导致了大量的请求挂起甚至超时。这是因为,我们即使在CreateTime上建立了索引,但是,如果使用了运算函数,查询一样会进行全表的检索。

所以,我们可以改成这样:

select * from Order where CreateTime > '2018-1-1 00:00:00'

当查询允许Null值的列时,需要特别注意

我们在创建表的字段时,如果这个字段需要作为索引时,尽量不要允许Null。因为,单列索引不会存Null值,复合索引不存所有索引列都为Null的值,所以如果列允许为Null,可能会得到“不符合预期”的结果集。

例如:我们有一个User表,其中有UserName字段记录了用户的名字,并且添加了索引。

现在我们执行了这样一个查询:

select * from User where UserName != '小倩'

但结果是这样的

aaarticlea/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==" alt="" data-ratio="0.20207253886010362" data-src="https://mmbiz.qpic.cn/mmbiz_jpg/tuSaKc6SfPrqwwm5MKPe3iaIicWXibqn4RPG0bDVv6DsShyGdDfZffX1VzqeXpOicq75ibcibfGkmrxerwe580VOSLQg/640" data-type="jpeg" data-w="193" />

那位UserName为Null的数据并没有能包括进来。因此,如果我们想要包含这个用户的话,最好能够设置一个默认值。

复合索引,使用时要注意顺序

登录,肯定是我们使用得最多的一个查询了,为了保证效率,我们为LoginID和Password加上了复合索引。

当我们使用

select * from User where LoginID = '{LoginID}' and Password = '{Password}'
select * from User where Password = '{Password}' and LoginID = '{LoginID}'

查询时,都是能够准备的命中索引。当我们使用:

select * from User where LoginID = '{LoginID}' 

查询时,也是能够命中索引的。但是,当我们使用

select * from User where Password = '{Password}' 

查询时,确无法命中索引,这是什么原因呢?

这是由于,复合索引对于查询的顺序是非常的铭感的,所以,符合索引中包含了几种规则,其中就有全列匹配和最左前缀匹配。

当所有列都能够匹配时,虽然查询的顺序上有不同,但是查询优化器会将顺序进行调整,以满足适合索引的顺序,所以,顺序的颠倒是没有问题的。

但是,如果所有列不能匹配时,就必须满足最左前缀匹配了,也就是,必须按照从左到右的顺序进行排列。因此,当我们建立是索引是<LoginID, Password>时,where Password = '{Password}' 就不满足最左前缀规则,无法命中索引了。

结果唯一时,别闷着

通常,我们设计User表时,并不会把LoginID作为主键,但是,LoginID确会在业务逻辑中验证唯一性,因此,如果使用

select * from User where LoginID = '{LoginID}'

查询时,结果一定只有一条。但是,数据库是不知道的,即使找到了这唯一的一条结果,他也会一直继续,直到扫描完所有的数据。

因此,在执行这样的查询时,我们可以优化一下,改成:

select * from User where LoginID = '{LoginID}' limit 1

这样,当查询到结果时,就不会再继续了。

最后,上面所有的例子都是坑

尽量少用或别用Select *,我们的查询其实都是有目的的,就好像登录一样,我们其实只需要知道有结果返回就行了,使用select count(0)就可以了,但是我们使用select * 的话,就会消耗大量无效的数据库内存。

SQL这样干,你就是给自己刨坑.....的更多相关文章

  1. RocketMQ事务消息学习及刨坑过程

    一.背景 MQ组件是系统架构里必不可少的一门利器,设计层面可以降低系统耦合度,高并发场景又可以起到削峰填谷的作用,从单体应用到集群部署方案,再到现在的微服务架构,MQ凭借其优秀的性能和高可靠性,得到了 ...

  2. 一次php访问sql server 2008的API接口的采坑

    2018年6月21日17:17:09,注意:不是详细文档,新手可能会看不懂 windows下安装 项目是sql server 2008的k3,php连接数据库写的API,因为是买的时候是别人的程序,测 ...

  3. Vue刨坑

    vue常见问题 1.在自定义组件里,你可以像任何普通元素一样用v-for.eg1: <my-component v-for="item in items"></m ...

  4. SQL SERVER CEILING 函数 取整时的坑。。。

    CEILING ---返回大于或等于指定数值表达式的最小整数 当舍去同一个大小的值 但是正负方向不一致时要注意小数位四舍五入的问题   例如: SELECT CEILING($123.45), CEI ...

  5. springboot+thymeleaf刨坑——首页加载js/css等失败解决方法

    在使用thymeleaf加载css或js样式,当我们进入登录页的时候发现,所有的样式都是加载失败的.原因是在新版中有这样一个坑……: 当我们设置了addInterceptors-注册拦截器的时候,通常 ...

  6. HAService 刨坑

    High availability is a characteristic of a system, which describes the duration (length of time) for ...

  7. vue刨坑(二)

    vue实例 vue实例 每一个应用都是通过vue这个构造函数创建根实例(root instance),启动 new vue(选项对象) 需要传入选项对象,对象包含挂载元素,数据,模板,方法等. el: ...

  8. 夜黑风高的夜晚用SQL语句做了一些想做的事·······

         IT这条漫漫长路注定是孤独的,陪伴我们的只有那些不知冷暖的代码语句和被手指敲打的磨掉了键上的标识的键盘. 之所以可以继续坚持下去,是因为心中有一份永不熄灭的激情. 成功的路上让我们为自己带盐 ...

  9. LINQ to SQL使用教程

    前些时间用LINQ to SQL做了一些项目,现在打算总结一下,帮助新手快速入门,并写一些别的教程没提到的东西. 一.LINQ to SQL和别的LINQ to XXX有什么关系?二.延迟执行(Def ...

随机推荐

  1. python3笔记十七:python文件读写

    一:学习内容 读文件 写文件 编码与解码 二:读文件--步骤分解 1.过程 第一步:打开文件第二步:读文件内容第三步:关闭文件 2.第一步:打开文件 open(path,flag[,encoding] ...

  2. SRS之HLS部署实例源码分析

    1. 综述 SRS 关于 HLS 的具体配置可见: HLS部署实例 SRS 关于 hls 的配置文件内容如下: listen 1935; max_connections 1000; daemon of ...

  3. jmeter源代码开发环境构建

    1.下载jmeter源码:http://jmeter.apache.org/download_jmeter.cgi 2.新建-->java Project-->Next-->src- ...

  4. jdk git maven Jenkins的配置

    前言 搭建Jenkins的笔记. JDK 1.  jdk 下载地址 https://www.oracle.com/technetwork/java/javase/downloads/jdk8-down ...

  5. mvp解读

    mvp存在的问题 1.业务复杂时,可能使得Activity变成更加复杂,比如要实现N个IView,然后写更多个模版方法. 2.业务复杂时,各个角色之间通信会变得很冗长和复杂,回调链过长. 3.Pres ...

  6. 如何评价深度学习框架Keras?

    python机器学习-乳腺癌细胞挖掘(博主亲自录制视频)https://study.163.com/course/introduction.htm?courseId=1005269003&ut ...

  7. Redis常见报错之 Redis::CommandError (MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk)

    在Redis运行过程中,报错信息如下: Redis::CommandError (MISCONF Redis is configured to save RDB snapshots, but it i ...

  8. pandas之数据处理操作

    1.pandas对缺失数据的处理 我们的数据缺失通常有两种情况: 1.一种就是空,None等,在pandas是NaN(和np.nan一样) 解决方法: 判断数据是否为NaN:pd.isnull(df) ...

  9. vuex 使用

    一.什么是Vuex Vuex是一个专门为Vue.js应用程序开发的状态管理模式, 它采用集中式存储管理所有组件的公共状态, 并以相应的规则保证状态以一种可预测的方式发生变化 二. 为什么要使用Vuex ...

  10. Python——作业12(选做)选中矩阵的每行或每列画出对应的折线图(python programming)

    import os import platform import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5 ...