原文转载至:https://www.cnblogs.com/lyhabc/p/3378753.html

like语句百分号前置会使用到索引吗?

前几天看了这篇文章:谈SQL Server对like '%关键词%' 处理时的索引利用问题

看完了之后,我很想知道这篇文章是不是临时工写的?还是网站的主人写的,网站的主人的微博我都有关注(在微博里私信过)

是某个公司的DBA,这里先不管他是不是临时工写的,今天我也研究一下这个问题o(∩_∩)o

说明:我们说的走索引指的是:聚集索引查找、非聚集索引查找

而全表扫描、聚集索引扫描、非聚集索引扫描都不是走索引

而这里说的走索引跟全文搜索/全文索引没有关系  SQLSERVER全文搜索

全文搜索/全文索引已经是另外一种技术了


聚集索引表
SQL脚本如下:

 View Code

表数据

聚集索引创建在GROUPNAME这个字段上,我们就查找GROUPNAME这个字段

如果看过我以前写的文章的人肯定知道:查找只会出现在建立索引的时候的第一个字段(这里我就不再详细叙述了)

1 --聚集索引查找
2 SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '销售组1000'
3 --聚集索引扫描
4 SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '%销售组1000%'
5 --聚集索引扫描
6 SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '%销售组1000'
7 --聚集索引查找
8 SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '销售组1000%'

--------------------------------------------------------------------------

IO和时间统计

 View Code
 1 (1 行受影响)LIKE '销售组1000'2 表 'Department'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。3 4 SQL Server 执行时间:5    CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。6 7 SQL Server 执行时间:8    CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。9
10 (11 行受影响)LIKE '%销售组1000%'
11 表 'Department'。扫描计数 1,逻辑读取 448 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
12
13 SQL Server 执行时间:
14    CPU 时间 = 47 毫秒,占用时间 = 47 毫秒。
15
16 SQL Server 执行时间:
17    CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
18
19 (1 行受影响)LIKE '%销售组1000'
20 表 'Department'。扫描计数 1,逻辑读取 448 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
21
22 SQL Server 执行时间:
23    CPU 时间 = 47 毫秒,占用时间 = 40 毫秒。
24
25 SQL Server 执行时间:
26    CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
27
28 (11 行受影响)LIKE '销售组1000%'
29 表 'Department'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
30
31 SQL Server 执行时间:
32    CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
33
34 SQL Server 执行时间:
35    CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。

只有LIKE '销售组1000'LIKE '销售组1000%'用到了查找

为什麽?我会在文中最后说明


非聚集索引表

SQL脚本如下:

我们drop掉刚才的department表

1 DROP TABLE [dbo].[Department]

重新建立department表

 View Code

非聚集索引依然建立在GROUPNAME这个字段上

表数据

同样,我们使用上面讲解聚集索引表时候的查询语句

1 --非聚集索引查找  RID查找
2 SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '销售组1000'
3 --非聚集索引扫描  RID查找
4 SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '%销售组1000%'
5 --非聚集索引扫描   RID查找
6 SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '%销售组1000'
7 --非聚集索引查找    RID查找
8 SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '销售组1000%'

因为是select * 所以SQLSERVER需要到数据页面去找其他的字段数据,使用到RID查找

这里的结果跟聚集索引是一样的

-------------------------------------------------------------------------------------------

IO和时间统计

 View Code
 1 (1 行受影响) LIKE '销售组1000'2 表 'Department'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。3 4 SQL Server 执行时间:5    CPU 时间 = 0 毫秒,占用时间 = 62 毫秒。6 7 SQL Server 执行时间:8    CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。9
10 (11 行受影响)LIKE '%销售组1000%'
11 表 'Department'。扫描计数 1,逻辑读取 92 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
12
13 SQL Server 执行时间:
14    CPU 时间 = 16 毫秒,占用时间 = 17 毫秒。
15
16 SQL Server 执行时间:
17    CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
18
19 (1 行受影响)LIKE '%销售组1000'
20 表 'Department'。扫描计数 1,逻辑读取 82 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
21
22 SQL Server 执行时间:
23    CPU 时间 = 15 毫秒,占用时间 = 17 毫秒。
24
25 SQL Server 执行时间:
26    CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
27
28 (11 行受影响)LIKE '销售组1000%'
29 表 'Department'。扫描计数 1,逻辑读取 13 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
30
31 SQL Server 执行时间:
32    CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
33
34 SQL Server 执行时间:
35    CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。


为什麽只有LIKE '销售组1000'和LIKE '销售组1000%'用到了查找???

如果阁下曾经有看过我写的

SQLSERVER聚集索引与非聚集索引的再次研究(上)
SQLSERVER聚集索引与非聚集索引的再次研究(下)

您就会知道在聚集索引页面和非聚集索引页面里都有一个KeyHashValue的字段

聚集索引页面

非聚集索引页面

当使用 '%销售组1000%'和'%销售组1000'的时候,因为是模糊匹配(百分号前置)

SQLSERVER不会去匹配hash值(KeyHashValue),直接扫描(SCAN)算了

但是使用'销售组1000'和'销售组1000%'的时候

'销售组1000' :SQLSERVER能够准确匹配到唯一的一个hash值

'销售组1000%':SQLSERVER会匹配与销售组1000相同的hash值

销售组1000%匹配的记录会有多个,所以逻辑读取次数也会有多次

所以,'销售组1000'和'销售组1000%'能够使用查找(SEEK)


总结

只有了解了SQLSERVER的内部原理,才能够明白更多

注意:我这里并没有将非聚集索引扫描纳入到“走索引”这个分类,如果将非聚集索引扫描纳入到“走索引”这个分类里

那么我的朋友的文章就是对的,随便加个非聚集索引,让表扫描/聚集索引扫描变成非聚集索引扫描,就认为是走索引

(虽然非聚集索引扫描比聚集索引扫描/表扫描快,IO少)

那么下面四个语句都是属于走索引,没有什么好讨论的,我们讨论的前提是在基础表上不加任何东西,如果在做实验的过程中

随便加个非聚集索引,然后走非聚集索引扫描就说走索引,那么这篇文章就没有意义了,经过再三斟酌,

我决定将“非聚集索引扫描”移出“走索引”这个分类,毕竟查找(SEEK)比扫描(SCAN)快


SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '销售组1000'
SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '%销售组1000%'
SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '%销售组1000'
SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '销售组1000%'

最最后,补充说一下

我们判断一个执行计划的性能的好坏的标准是什么??

就是哪个执行计划的逻辑读次数最少

Logical reads:包含该语句从内存数据缓冲区中访问的页数和从物理磁盘读取的页数。

如果全表扫描/聚集索引扫描所使用的逻辑读比聚集索引查找/非聚集索引查找使用的逻辑读要少,

或者全表扫描比非聚集索引扫描使用的逻辑读要少

那么SQLSERVER选择全表扫描/聚集索引扫描这个执行计划就是好的

有些人为了让SQLSERVER使用索引,不惜代价使用查询提示,让SQLSRVER去走索引,这样是得不偿失的

我们的最终目的是:减少逻辑读次数,不要为了索引而索引!!

当然,我这里的实验环境跟各位的真实环境会有差别,不过“逻辑读次数”这个标准无论是哪个环境都是一样的!!

我说完了,谢谢大家o(∩_∩)o

physical reads:表示那些没有驻留在内存缓冲区中需要从磁盘读取的数据页。
Read-ahead reads是SQL Server为了提高性能而产生的预读。

如有不对的地方,欢迎大家拍砖o(∩_∩)o

转载于:https://www.cnblogs.com/mkl34367803/p/9124600.html

like语句百分号前置会使用到索引吗?相关推荐

  1. mysql datetime month不走索引_like百分号加前面一定不走索引吗?一不小心就翻车,关于mysql索引那些容易错的点...

    like百分号加前面一定不走索引吗? 正常来讲,我们都知道在mysql的like查询中,百分号加在关键词后面是走索引的,比如 select * like "张三%",而百分号在前面 ...

  2. oracle图书操作、sql语句查询+授权、视图、索引、表操作

    oracle图书操作.sql语句查询+授权.视图.索引.表操作 一.创建一张表book,表结构为(总编号,分类号,书名,作者,出版单位,单价),插入若干记录 二.创建一张表reader,表结构为(借书 ...

  3. access 导入 txt sql语句_从零开始学习 MySQL 系列索引、视图、导入和导出

    阅读本文大概需要 8 分钟 前言上篇文章我们学习了数据库和数据表操作语句,今天我们学习下数据库索引,视图,导入和导出的知识.作为基础篇,不会涉及到关于索引和视图的高级应用和核心概念,但是基本操作大家会 ...

  4. sql语句优化之一:尽量使用索引避免全表扫描

    url:http://lzz7658823.iteye.com/?page=3 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量 ...

  5. c oracle 多条语句,Oracle 实践:如何编写一条 sql 语句获取数据表的全部索引信息(兼容 Oracle 19c、Oracle 11g)...

    一.引言 部门使用 Oracle 已经有一些时日,最近在工作中遇到了这么一个需求: 我们希望拿到某些数据表的全部索引信息,对索引信息进行检查,检查是否有漏掉没有创建的索引 这个需求,核心的点在于,我需 ...

  6. mysql中索引创建 查看和删除语句_MySQL如何创建和删除索引?

    mysql索引,mysql创建索引,mysql删除索引 1.在关系数据库中,索引是一种与表有关的数据库结构,它可以使对应于表的SQL语句执行得更快.今天就简单地给大家演示一下mysql中索引的创建,查 ...

  7. sql简单带索引的语句_SQL Server 2017:栏目索引和简单计划

    sql简单带索引的语句 Some time ago, SQL Server 2017 was released and issued as CTP. The most exciting release ...

  8. SQL高级语句-DROP 语句,可以轻松地删除索引、表和数据库。

    DROP INDEX 语句 我们可以使用 DROP INDEX 命令删除表格中的索引. 用于 Microsoft SQLJet (以及 Microsoft Access) 的语法: DROP INDE ...

  9. 我的MYSQL学习心得(十六) 优化

    原文:我的MYSQL学习心得(十六) 优化 我的MYSQL学习心得(十六) 优化 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看 ...

最新文章

  1. ​京东AI研究院获QuAC机器阅读理解竞赛冠军,EL-QA模型能力业界领先
  2. 解决403跨域问题之——————JSONP
  3. 使用gparted-LiveCD对centos分区调整---virtualbox磁盘调整序2
  4. 数学史思维导图_【学科活动】思维导图展风采,数学文化提素养——庆云县第四中学(北校区)四年级数学组活动小记...
  5. 智能会议系统(17)--- Linphone用户注册
  6. 美国爱荷华州批准参议院541号文件,允许使用分布式账本技术和智能合约
  7. 2018-2019 ACM-ICPC, Asia Jiaozuo Regional Contest题解
  8. 图论算法——有向图的可达性与寻路
  9. jquery省市插件
  10. android 微信小程序 唤起app,Android 微信小程序打不开app方案解决
  11. Tomcat日志分割
  12. linux系统可以用autocad吗,还在找适用于Linux系统的CAD软件?这5款千万别错过!
  13. VOC2007和COCOmAP计算
  14. 实现原理 扫描枪_条码扫描枪的原理
  15. 【刷题】BZOJ 1487 [HNOI2009]无归岛
  16. 学而思python分几个level_学而思数学分几个等级
  17. 计算机移动硬盘无法访问,移动硬盘无法访问参数不正确的解决方法
  18. [SIGMOD 2021] SharPer: Sharding Permissioned Blockchains Over Network Clusters
  19. 第一次创建百度脑图介绍自己,把创建过程分享一下吧,嘿嘿。
  20. python爬虫学习(循环爬取网页链接)

热门文章

  1. Visual Studio——理解多字节编码与Unicode码
  2. iOS - PassData
  3. 使用intellij的svn时提示出错: Can't use Subversion command
  4. Nginx源码分析(3)
  5. 存储IOPS参数结合实例详解
  6. 回头看医疗行业信息化,怎一个乱字了得
  7. 10. http 的一些说明及分析工具
  8. occam‘s razor
  9. why carbon 13?
  10. bucket sort count sort