首页 > 数据库 >MYSQL 8 中间字段有NULL 值,还是无法走索引,所以我高估了MYSQL 的查询智商

MYSQL 8 中间字段有NULL 值,还是无法走索引,所以我高估了MYSQL 的查询智商

时间:2023-06-21 10:00:49浏览次数:42  
标签:复合 查询 索引 字段 MYSQL NULL


MYSQL  8  中间字段有NULL 值,还是无法走索引,所以我高估了MYSQL 的查询智商_mysql

开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。

基于半瓶子咣当的状态,PG, MYSQL , POLARDB , MONGODB ,REDIS 还是都能舞刀弄枪几下的,但是这个弄这弄着,这记忆力就会不好,因为我一直对于MYSQL 8 的优化器的进步,表达了一个满意的记忆,虽然你比不了,oracle, sql server ,pg ,但是MYSQL 也差不太多了,实际上教育了我,版本MYSQL 8.013(生产) 试验 8.030 实际上这二者在这个问题上没有差别。当然也再次印证了, 开源数据库一定在某些方面是给你一个  disabled 的 状态,否则怎么就商业数据库卖钱呢,不同意的参见,今天一起发的 POSTGRESQL EDB 公司的文章, PG ,MYSQL 同时都能印证,不花钱的产品,你要求别太高。

废话太多,在生产上的一个表字段中包含了连续了  A  + B + C  A 为字符,B 为字符,C为日期,索引中也是这样建立的,A B C ,但是在查询中出现了 A + C (C为范围查询),虽然实际上走了我们建立的索引,但是实际上,和没走也差不多。下面用一个实例来反馈

测试数据100万

MYSQL  8  中间字段有NULL 值,还是无法走索引,所以我高估了MYSQL 的查询智商_数据库_02

select * from test_innodb where user_id = '00OSL5Whq664QQzaYbOp' and create_time >= '2023-04-14 10:00:00' and create_time < '2023-04-19 10:00:00';

语句很简单,另外数据中在生产系统中,user_id 的位置并不是唯一值,而测试系统中是唯一值,group_id 不是唯一值,并且里面有NULL ,时间就是我们的时间,没有空值。

索引我们先建立三个字段的,然后执行了查询语句。从图中看,我们可以看到走了三个字段的联合索引,但是基本上在选择字段部分仅仅是使用 user_id 作为实际索引使用的部分。

MYSQL  8  中间字段有NULL 值,还是无法走索引,所以我高估了MYSQL 的查询智商_mysql_03

在我们创建了仅仅有 user_id 和 create_time 的索引,我们再次运行语句,可以看到整体的执行的中的执行计划,是走了索引的全部

MYSQL  8  中间字段有NULL 值,还是无法走索引,所以我高估了MYSQL 的查询智商_数据库_04

我的问题就来了,这个为什么同样的数据库同样的语句,同样的MYSQL,执行计划中,仅仅是一个索引,中间多个一个字段,就忽略了后面的日期范围部分,WHY ,我的记忆是MYSQL 是可以跳过索引中间有字段但是查询里面没有需求的字段。

原因是为什么在 MySQL 中,当使用复合索引(包含多个字段的索引)时,如果中间字段的值为 NULL,那么将仅会走前缀。也就是说,复合索引只有在所有前面字段的值都非 NULL 时,才能被用来检索。

例如,假设我们有一个包含三个字段(a, b, c)的复合索引:

CREATE INDEX idx_example ON table_name (a, b, c);

以下查询可以使用复合索引 idx_example

SELECT * FROM table_name WHERE a = 1 AND b = 2;

但是,如果字段 b 的值为 NULL,那么复合索引将只能走前缀,即只会用到字段 a

SELECT * FROM table_name WHERE a = 1 AND b IS NULL;

此时,索引将不再涉及字段 c,因为字段 b 的值为 NULL,导致索引只能走前缀。

那么别的数据库是否也有这个问题,我们来看看 MYSQL 的死对头 POSTGRESQL 

在 PostgreSQL 中,当使用复合索引(包含多个字段的索引)时,即使中间字段的值为 NULL,该复合索引仍可以用于查询。这是因为 PostgreSQL 对 NULL 值进行了特殊处理,将其包含在索引内。这种行为与 MySQL 不同。

例如,假设我们有一个包含三个字段(a, b, c)的复合索引:

CREATE INDEX idx_example ON table_name (a, b, c);

以下查询可以使用复合索引 idx_example:

SELECT * FROM table_name WHERE a = 1 AND b = 2;

同时,当字段 b 的值为 NULL 时,PostgreSQL 也能够使用该复合索引:

SELECT * FROM table_name WHERE a = 1 AND b IS NULL;

在这个例子中,即使 b 字段的值为 NULL,索引依然可以被用来检索。

那么到此为止,同为免费数据库的POSTGRESQL 是可以在这样的情况来使用索引的,那么我们就会引发一个MYSQL 性能差另一个问题

在查询中,MYSQL 可能会由于应付上面的查询,需要建立更多的索引来满足查询的性能要求,而其他的数据库则不需要,一个索引基本上可以搞定。

最终导致MYSQL 的查询,插入,删除等性能都相对于其他的数据库低下。好吧,不能说下去,MYSQL的FUNS 已经举着刀杀来了。 

MYSQL  8  中间字段有NULL 值,还是无法走索引,所以我高估了MYSQL 的查询智商_mysql_05

标签:复合,查询,索引,字段,MYSQL,NULL
From: https://blog.51cto.com/u_14150796/6527491

相关文章

  • MySQL一个关于derived table的bug描述与规避
    关联文章:MySQL对derivedtable的优化处理与使用限制一、Bug描述同事遇到一个有意思的语句,说一条SQL在MySQL8.0.25版本运行出的结果明显与给定的where条件不符,而在8.0.26版本上是正常的,语句上加了一个无关的用户变量后在8.0.25版本上结果才是正确的,想不通这是怎么回事,这么有......
  • mysql备份文件存储
    #########################                   ##########################......
  • mysqldump做主从
    1、主库备份timemysqldump--protocol=socket-S/data/mysql/data/mysql.sock--master-data=2--single-transaction-p-A>/data/mysqldump_date+%Y%m%d.sql2、scp到从库3、从库停止slave:stopslave;resetslaveall;4、source主库的备份文件5、查看标记binlog与poshead-100m......
  • MySQL-索引使用规则
    1最左前缀法则如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。如果跳跃某一列,索引将会部分失效(后面的字段索引失效)。showindexfromtb_user;对于最左前缀法则指的是,查询时,最左边的列,也就是profession必须存在,否则......
  • mysql8修改大小写敏感配置
      前两天遇到一个问题,同样的步骤二进制安装mysql,有的大小写敏感,而有得不存在,而当他们做主从时就会产生问题,这里我们对主库进行了一个配置文件更改,如果直接更改就会提示数据目录的大小写敏感为1,而配置为0,mysql启动就会失败,只能通过目录拷贝,修改配置文件、重启的方式修改。1、停......
  • 使用python对AWS-CloudTrail-Json-日志文件key字段名称的提取
    关于AWS CloudTrail-在Console界面,默认只能看到最近90天的数据如果需要追踪更早的操作记录,得需要配置CloudTrail日志输出保存到s3在s3上不同的region位于不同的目录,最后会将某一天的日志,存放到那一天的目录/文件夹中,目录路径格式(部分)如:aws-account-xxx/CloudTrail/cn-nort......
  • mysql事务阻塞原因探索
    –先保存现场showengineinnodbstatus;–查看是否存在锁等待信息showstatuslike‘innodb_row_lock%’;–查看锁等待的事务信息select*from information_schema.INNODB_TRXWHEREtrx_state=‘LOCKWAIT’;–查看锁等待的事务id,processId,阻塞它的事务id,阻塞它的pr......
  • MySQL的7种连接
    MySQL的七种连接刚学习Java和数据库,文章中讲的不对的地方,还请各位大神多多指教!本文参考链接(https://blog.csdn.net/qq_50596778/article/details/123145434)————————————————版权声明:本文为CSDN博主「NeverOW」的原创文章,遵循CC4.0BY-SA版权协议,转载请附......
  • MYSQL 执行update语句时报错: The total number of locks exceeds the lock table size
    由于数据量较大导致报错:‘’Thetotalnumberoflocksexceedsthelocktablesize‘’。这句话翻译过来大概是这个意思:总数已经超过锁定表的大小。解决办法:输入查询:showvariableslike"%_buffer%";找到innodb_buffer_pool_size对应的值默认为8388608也就是8兆。我们将其设置......
  • MySQL 如何查看表的大小
    1.查看所有数据库容量大小selecttable_schemaas'数据库',sum(table_rows)as'记录数',sum(truncate(data_length/1024/1024,2))as'数据容量(MB)',sum(truncate(index_length/1024/1024,2))as'索引容量(MB)'frominformation_schema.tablesgro......