千家信息网

MySQL中因字段字符集不同导致索引不能命中的解决方法

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,什么是索引?为什么要建立索引?索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的列有一
千家信息网最后更新 2026年10月31日MySQL中因字段字符集不同导致索引不能命中的解决方法

什么是索引?为什么要建立索引?

索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的列有一个索引,MySQL能够快速到达一个位置去搜索数据文件,而不必查看所有数据,那么将会节省很大一部分时间。

例如:有一张person表,其中有2W条记录,记录着2W个人的信息。有一个Phone的字段记录每个人的电话号码,现在想要查询出电话号码为xxxx的人的信息。

如果没有索引,那么将从表中第一条记录一条条往下遍历,直到找到该条信息为止。

如果有了索引,那么会将该Phone字段,通过一定的方法进行存储,好让查询该字段上的信息时,能够快速找到对应的数据,而不必在遍历2W条数据了。其中MySQL中的索引的存储类型有两种:BTREE、HASH。 也就是用树或者Hash值来存储该字段,要知道其中详细是如何查找的,就需要会算法的知识了。我们现在只需要知道索引的作用,功能是什么就行。

引言

今天写了一个sql,其中涉及的表中的数据量都差不多为50w左右,查询发现用了8s。这个只是测试服上数据,放到正式服上,肯定一运行就挂了。

SELECT Orders. NO, GuidNo, Orders.CreateTime, sum(OrderItem.Quantity) AS Quantity, Brand. NAME AS BrandName, member.Mobile, Street AS deliveryaddress, AreaFROM OrdersINNER JOIN OrderItem ON Orders.GuidNo = OrderItem.OrderGuidNoINNER JOIN Brand ON Brand.Id = Orders.BrandIdINNER JOIN member ON member.Id = 13INNER JOIN memberaddress ON member.Id = memberaddress.MemberIdWHERE orders.GuidNo IN (  SELECT   orderpayment.OrderGuidNo  FROM   paymentrecord  LEFT JOIN orderpayment ON paymentrecord.`No` = orderpayment.PaymentNo  WHERE   paymentrecord.PaymentMethod = 'MemberCard'  AND paymentrecord.Payer = 13 )GROUP BY GuidNo;

然后就用EXPLAIN分析了一下,发现Orders表没有命中索引,但是查询Orders中的GuidNo已经设置了索引,但就是不能命中。

解决过程

然后我将上面的语句分为两个语句。首先将sql语句修改为:将子查询的数据直接写在了sql中,查询用了0.12s。

SELECT Orders. NO, GuidNo, Orders.CreateTime, sum(OrderItem.Quantity) AS Quantity, Brand. NAME AS BrandName, member.Mobile, Street AS deliveryaddress, AreaFROM OrdersINNER JOIN OrderItem ON Orders.GuidNo = OrderItem.OrderGuidNoINNER JOIN Brand ON Brand.Id = Orders.BrandIdINNER JOIN member ON member.Id = 13INNER JOIN memberaddress ON member.Id = memberaddress.MemberIdWHERE orders.GuidNo IN (  '0A499C5B1A82B6322AE99D107D4DA7B8',  '18A5EE6B1D4E9D76B6346D2F6B836442',  '327A5AE2BACEA714F8B907865F084503',  'B42B085E794BA14516CE21C13CF38187',  'FBC978E1602ED342E5567168E73F0602' )GROUP BY GuidNo

第二个:单独运行子查询的Sql,也才用了0.1s

SELECT   orderpayment.OrderGuidNo  FROM   paymentrecord  LEFT JOIN orderpayment ON paymentrecord.`No` = orderpayment.PaymentNo  WHERE   paymentrecord.PaymentMethod = 'MemberCard'  AND paymentrecord.Payer = 13

这么问题就清晰了,一定是子查询和父查询关联的问题。因为子查询单独很快,父查询用子查询数据直接查的时候也很快,就是在他俩结合的时候很慢。大致能将问题锁定在这两个关联字段OrderGuidNo上。

最后发现 orderpayment 表和 Orders 表字符集是不同的。一个表的字符集是:utf8_general_ci,一个是:utf8mb4_general_ci。(不查不知道,发现一个数据库中,很多表的字符集都不相同)

修改orderpayment表的字符集和表中OrderGuidNo的字符集为:utf8_general_ci

ALTER TABLE orderpayment DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; //修改表的字符集ALTER TABLE orderpayment CHANGE OrderGuidNo OrderGuidNo VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci; //修改字段的字符集

然后在用EXPLAIN分析一下,可以看到都用上了索引。

然后运行,查询了0.112秒。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。

查询 索引 数据 字符 字段 字符集 信息 就是 语句 问题 存储 运行 两个 内容 号码 很快 时候 时间 电话 电话号码 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网是第几次科技革命的成果 互联网科技工作委员会主任 中国互联网科技股 猪兼强互联网科技 狮子座互联网科技培训 长亮科技互联网金融 科技互联网创业计划书 互联网金融和金融科技 互联网科技创新企业排名 互联网之后的科技是什么 港股科技和互联网 本届互联网博览会上的黑科技 工业互联网等科技实现智能化赋能 保险科技服务互联网营销体系 互联网公司高科技产品 电子商务与互联网科技的关系 下一代互联网重大应用科技园 上海乐五互联网科技有限公司 同城互联网络科技 银川新华互联网科技学校原画 礼当家互联网科技 互联网科技股票 奇酷互联网科技公司 长亮科技互联网金融 银川新华互联网科技学校地址 科技与互联网哪个更好 彤创互联网科技有限公司 互联网公司属于科技吗 张家口科技产业互联网平台 深圳互联网科技园地址
0