热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

实操演示——那些造成数据库全表扫描的坑

本文所有示例都使用的是MySQL和DBeaver。为了直观地认识到哪些写法会容易导致全表扫描,我们这里进行实际操作。我们先创建一张学生表:

本文所有示例都使用的是MySQL和DBeaver。

为了直观地认识到哪些写法会容易导致全表扫描,我们这里进行实际操作。

我们先创建一张学生表:

create table test_student(
    id int primary key auto_increment,
    name varchar(100),
    gender varchar(2),
    age int,
    address varchar(200),
    email varchar(100),
    grade varchar(2)
)

在这张表中,除了主键id有主键索引外,其它字段暂时都没有索引。然后再初始化一些数据:

create
    procedure test_batch_insert()
begin
    declare cnt int default 0;

while cnt 

初始化的数据各位可以自行定义,此处仅供参考。

  1. 整个SQL语句中没有where子句。
实操演示——那些造成数据库全表扫描的坑
没有where导致的全表扫描

类型为ALL就代表全表扫描,在后面的键列都是空的,说明此次查询没有可以使用的键。

建议:任何语句包括delete、update等,都一定要加上where条件,除了防止全表扫描,更要防止大规模地误修改了数据。

如果你就是要修改表中的所有数据怎么办?如果你就是不在乎是否走索引怎么做?可以加上where created_date ,如此虽然性能上可能没有实质性提升,但好歹显得更加规范了。

  1. 查询条件列虽然有索引,但是where筛选条件中使用了is null或者is not null

    我们先给name字段加上索引:

    alter table test_student add index name_index(name);

    然后看看是否索引有效。

实操演示——那些造成数据库全表扫描的坑
索引有效的情况

此时在执行计划里面可以看到,类型是ref,此次查询使用的键就是我们刚刚创建的索引name_index,证明索引有效。然后我们把查询条件的name改为使用is null或者is not null试试:

实操演示——那些造成数据库全表扫描的坑
is null导致的全表扫描
实操演示——那些造成数据库全表扫描的坑
is not null导致的全表扫描

我们看到,查询条件列虽然有索引,但是如果使用了is null或者is not null就全表扫描了。

建议:在设计表的时候,就应该考虑到,将那些可能会被用作查询条件的列设置为not null,不允许该列出现空值,并指定该列的默认值。

  1. 查询条件列虽然有索引,但是where筛选条件中使用了!=或者操作符。

    我们还是基于上面的查询语句做下变更:

实操演示——那些造成数据库全表扫描的坑
使用!=导致的全表扫描
实操演示——那些造成数据库全表扫描的坑
使用导致的全表扫描

但是如果我们使用,=,=,between,in以及部分like的场景,都是可以走索引的,下面我们仅仅针对in的情况给出示例:

实操演示——那些造成数据库全表扫描的坑
使用in的时候可以走索引
  1. 查询条件列虽然有索引,但是不恰当地使用了like。

    当需要模糊查询的时候,需要避免使用前模糊,我们先来看下使用前模糊造成的后果:

实操演示——那些造成数据库全表扫描的坑
使用前模糊导致的全表扫描

但是如果我们使用后模糊查询,就会走索引:

实操演示——那些造成数据库全表扫描的坑
使用后模糊的时候可以走索引
  1. 查询条件列虽然有索引,但是在查询条件列上使用了函数或者计算操作。

    我们先给年龄字段也加上索引。

    alter table test_student add index age_index(age);

    然后普通的索引列查询是走索引的,没有问题。

实操演示——那些造成数据库全表扫描的坑
年龄字段正常走索引

我们在年龄字段虽然加上了索引,但是如果在查询的时候加上了计算:

实操演示——那些造成数据库全表扫描的坑
索引列加上计算导致的全表扫描

如果使用函数:

实操演示——那些造成数据库全表扫描的坑
索引列加上函数导致的全表扫描

建议:

可以把ts.age/2 = 11改成ts.age = 22,计算操作挪到等号右边。

  1. 查询条件列虽然有索引,但是在查询条件列上发生了隐式转换。

    比如我们现在有个记录的name字段值为2,然后我们以字符串形式查询时没有问题:

实操演示——那些造成数据库全表扫描的坑
索引查询

但是如果我们使用数值进行查询,就发生了隐式转换,系统自动将数值转换为字符串再查询:

实操演示——那些造成数据库全表扫描的坑
索引列发生隐式转换导致的全表扫描

但是如果我们自己做了显式转换,就没有问题,索引仍旧可以使用:

实操演示——那些造成数据库全表扫描的坑
索引列显式转换
  1. 查询条件列虽然有索引,但是在查询条件列上数据的区分度不明显。

    我们先来给年级字段也加上索引。

    alter table test_student add index grade_index(grade);

    然后使用该索引列发起查询:

实操演示——那些造成数据库全表扫描的坑
索引列数据区分度不大导致的全表扫描

因为真实数据中的该列值除了1就是2,所以区分度不大时也无法使用索引。

本文持续更新中,欢迎增加。


推荐阅读
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • PHP设置MySQL字符集的方法及使用mysqli_set_charset函数
    本文介绍了PHP设置MySQL字符集的方法,详细介绍了使用mysqli_set_charset函数来规定与数据库服务器进行数据传送时要使用的字符集。通过示例代码演示了如何设置默认客户端字符集。 ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 开发笔记:select from具体执行相关知识介绍及案例分析
    本文由编程笔记小编整理,主要介绍了select from具体执行相关的知识,包括数据插入、查询最小rowID、查询每个重复名字的最小rowID、删除重复数据等操作,并提供了案例分析。希望对读者有一定的参考价值。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
author-avatar
虹彩戳穿_525
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有