【数据库专题】实战演示造成数据库全表扫描的坑

简介: 【数据库专题】实战演示造成数据库全表扫描的坑

233.webp.jpg正文


一 创建表


1.1 我们先创建一张学生表:


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)
)


1.2 创建索引


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


create
    procedure test_batch_insert()
begin
    declare cnt int default 0;
while cnt < 100 do insert
    into
        test01.test_student (name,
        gender,
        age,
        address,
        email,
        grade)
    values(concat('unkonwn', cnt),
    '女',
    24 + cnt,
    '大唐长安',
    'libai@tang',
    '2');
set
cnt = cnt + 1;
end while;
end;
call test_batch_insert();

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


二 测试编写SQL进行测试


2.1整个SQL语句里没用where子句


223.png

没有where导致的全表扫描


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


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


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


2.2 添加where子句


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


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


alter table test_student add index name_index(name);


然后看看是否索引有效。

224.webp.jpg


索引有效的情况


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


225.png


is null导致的全表扫描


226.png


is not null导致的全表扫描


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


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


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


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


227.png


使用!=导致的全表扫描


228.png


使用<>导致的全表扫描


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


229.png


使用in的时候可以走索引


查询条件列虽然有索引,但是不恰当地使用了like。


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


230.png


使用前模糊导致的全表扫描


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


231.webp.jpg

使用后模糊的时候可以走索引


查询条件列虽然有索引,但是在查询条件列上使用了函数或者计算操作。


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


alter table test_student add index age_index(age);


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


234.webp.jpg


年龄字段正常走索引


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


235.png


索引列加上计算导致的全表扫描


如果使用函数:


115.png


索引列加上函数导致的全表扫描


建议:


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


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

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


114.png


索引查询


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


113.png


索引列发生隐式转换导致的全表扫描


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


112.png


索引列显式转换


查询条件列虽然有索引,但是在查询条件列上数据的区分度不明显。


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


alter table test_student add index grade_index(grade);


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


111.png


索引列数据区分度不大导致的全表扫描


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

相关文章
|
19天前
|
SQL 关系型数据库 数据库
国产数据实战之docker部署MyWebSQL数据库管理工具
【10月更文挑战第23天】国产数据实战之docker部署MyWebSQL数据库管理工具
58 4
国产数据实战之docker部署MyWebSQL数据库管理工具
|
9天前
|
存储 SQL 数据库
深入浅出后端开发之数据库优化实战
【10月更文挑战第35天】在软件开发的世界里,数据库性能直接关系到应用的响应速度和用户体验。本文将带你了解如何通过合理的索引设计、查询优化以及恰当的数据存储策略来提升数据库性能。我们将一起探索这些技巧背后的原理,并通过实际案例感受优化带来的显著效果。
28 4
|
1月前
|
SQL NoSQL 数据库
Cassandra数据库与Cql实战笔记
Cassandra数据库与Cql实战笔记
18 1
Cassandra数据库与Cql实战笔记
|
17天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
85 1
|
18天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
47 0
|
1月前
|
SQL 关系型数据库 MySQL
sql注入原理与实战(三)数据库操作
sql注入原理与实战(三)数据库操作
sql注入原理与实战(三)数据库操作
|
3月前
|
SQL 存储 NoSQL
Redis6入门到实战------ 一、NoSQL数据库简介
这篇文章是关于NoSQL数据库的简介,讨论了技术发展、NoSQL数据库的概念、适用场景、不适用场景,以及常见的非关系型数据库。文章还提到了Web1.0到Web2.0时代的技术演进,以及解决CPU、内存和IO压力的方法,并对比了行式存储和列式存储数据库的特点。
Redis6入门到实战------ 一、NoSQL数据库简介
|
1月前
|
SQL 数据处理 数据库
SQL语句优化与查询结果优化:提升数据库性能的实战技巧
在数据库管理和应用中,SQL语句的编写和查询结果的优化是提升数据库性能的关键环节
|
1月前
|
SQL 存储 Java
sql注入原理与实战(二)数据库原理
sql注入原理与实战(二)数据库原理
|
3月前
|
SQL 数据库
Spring5入门到实战------13、使用JdbcTemplate操作数据库(批量增删改)。具体代码+讲解 【下篇】
这篇文章是Spring5框架的实战教程,深入讲解了如何使用JdbcTemplate进行数据库的批量操作,包括批量添加、批量修改和批量删除的具体代码实现和测试过程,并通过完整的项目案例展示了如何在实际开发中应用这些技术。
Spring5入门到实战------13、使用JdbcTemplate操作数据库(批量增删改)。具体代码+讲解 【下篇】