MySQL is null 查询太慢的问题

本文探讨了20万条数据中,针对列column进行null查询和长度判断时的时间差异,重点关注字符类型列的效率提升策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 数据量 20万条

  • column is null查询所耗费时间 2.5s左右

  • length(column) is null查询耗费时间0.5s左右

该方法只适用于所判断列 column 为字符类型

<think>嗯,用户给了我一个SQL查询语句,让我分析它的查询条件和性能问题。首先,我需要仔细看一下这个SQL的结构和各个条件。让我先通读一遍这个查询。 这个查询是SELECT COUNT(*) FROM online_travel.scenic_ticket,后面跟着一堆WHERE条件。所有条件都是用AND连接的,也就是说需要同时满足这些条件才会被计数。看起来用户是想统计符合这些特定条件的记录数量。 首先,我要分析查询条件是否合理。比如,id = '-401993725',这里id字段的值是一个负数,而且被单引号括起来,可能意味着id字段是字符串类型?如果是数值类型的话,用单引号可能有问题,但不同数据库处理方式不同,比如MySQL可能会自动转换,但这样可能会影响性能。另外,scenicId IS NULL,还有cover、detail、number、price这些字段都是IS NULL,这可能表示这些字段在正常情况应该是有值的,但这里查询的是这些字段为空的情况。然后useStatus和isDelete都是等于'0',这里用字符串还是数值类型也需要确认。createTime和updateTime等于CURRENT_TIMESTAMP,这看起来可能有问题,因为CURRENT_TIMESTAMP通常是一个函数,返回当前时间,但这里被单引号括起来,变成了字符串比较,而不是动态的时间值。也就是说,这里可能是在查找createTime和updateTime等于字符串'CURRENT_TIMESTAMP'的记录,而不是实际的时间戳。这可能是一个错误。最后,telephone = '0532-85815137',电话号码是否正确存储需要确认,比如是否有区号或其他格式问题。 接下来是性能问题。首先,检查是否有合适的索引。这个查询涉及多个字段,如果这些字段的组合没有复合索引,那么数据库可能会进行全表扫描,尤其是当表的数据量很大时,性能会很差。特别是id字段作为主键的话,通常会有索引,但其他字段如scenicId、cover等如果没有索引,可能会影响查询速度。另外,对于COUNT(*)操作,如果表很大,即使有索引,统计行数也可能需要扫描索引,但具体取决于存储引擎,比如InnoDB和MyISAM处理COUNT(*)的方式不同。 另外,所有条件都是AND连接,且很多字段是IS NULL,这些字段的选择性如何?如果大部分记录这些字段都是NULL,那么过滤效果可能不好,导致扫描大量数据。比如,如果isDelete='0'表示未删除的记录,而大部分记录都是未删除的,那么这个条件的过滤效果就低,不能有效减少扫描的行数。 关于createTime和updateTime的条件,如果原本是想使用当前时间戳,那么这里的写法是错误的,应该使用函数而不是字符串,比如createTime = CURRENT_TIMESTAMP,但这样可能不太合理,因为时间戳通常不会等于当前时间,除非是实时插入的数据。所以这里可能存在逻辑错误,导致查询结果为空或者不符合预期。 还有telephone的条件,是否电话号码存储正确,比如是否包含区号或者其他符号,或者是否存在索引。如果电话号码字段没有索引,且数据量大,查询会变慢。 总结一下,查询条件可能存在逻辑问题,尤其是时间戳的比较,同时性能问题可能源于缺乏合适的索引,特别是复合索引,以及字段的选择性不高导致扫描大量数据。优化点可能包括修正时间条件的写法,添加合适的索引,检查字段数据类型是否匹配,以及确认查询逻辑是否正确。 用户可能需要知道如何优化这个查询的执行速度,以及如何调整查询条件以正确反映他们的意图。此外,用户可能还想了解如何分析执行计划,比如使用EXPLAIN来查看索引使用情况。</think>### SQL查询分析及优化建议 #### 一、查询条件分析 1. **数据类型隐患** - `id = '-401993725'`:若`id`字段为数值型,使用字符串格式可能导致隐式类型转换,影响索引使用[^2] - `createTime = 'CURRENT_TIMESTAMP'`:实际比较字符串而非时间戳,可能产生逻辑错误(正确写法应为`CURRENT_TIMESTAMP`不加引号) 2. **空值检查集中** 同时包含5个`IS NULL`条件(`scenicId`,`cover`,`detail`,`number`,`price`),建议确认业务逻辑是否允许这些核心字段全为空 3. **时间戳逻辑问题** `createTime`与`updateTime`同时等于固定时间值的情况,在正常业务场景中极难出现(通常`updateTime`会晚于`createTime`) #### 二、性能问题诊断 1. **索引缺失风险** 该查询包含10个WHERE条件字段,若未建立复合索引,将导致全表扫描。通过执行计划可验证: ```sql EXPLAIN SELECT COUNT(*) FROM `online_travel`.`scenic_ticket` WHERE ... ``` 2. **字段选择性不足** - `isDelete = '0'`:若该字段表示软删除标记,可能90%以上记录都满足此条件 - `useStatus = '0'`:状态类字段通常区分度较低 $$ \text{过滤效率} = \prod_{i=1}^{n} \text{字段选择性} $$ 3. **COUNT(*)优化空间** InnoDB引擎的COUNT操作需要遍历索引树,在亿级数据量下性能显著下降[^3] #### 三、优化方案 1. **索引优化** 建立覆盖索引(需权衡索引维护成本): ```sql ALTER TABLE `scenic_ticket` ADD INDEX idx_optimize ( `isDelete`, `useStatus`, `scenicId`, `telephone`, `createTime` ) ``` 2. **查询重写** 按字段过滤优先级调整条件顺序: ```sql SELECT COUNT(*) FROM `scenic_ticket` WHERE `telephone` = '0532-85815137' -- 高区分度条件前置 AND `createTime` = CURRENT_TIMESTAMP -- 修正时间条件 AND `id` = -401993725 -- 移除类型转换 AND `isDelete` = '0' ... ``` 3. **架构优化** 对频繁访问的统计类查询,建议: - 使用物化视图(MySQL 8.0+) - 定时任务+计数表 - 列式存储引擎 #### 四、执行计划验证 通过`EXPLAIN FORMAT=JSON`可获取详细成本分析: ```json { "query_block": { "cost_info": { "query_cost": "3247.52" // 优化目标应降至100以下 }, "table": { "index": "idx_optimize", // 验证索引命中 "rows_examined_per_scan": 158632 } } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值