Bohr-L Bohr-L
首页
技术
常见面试题
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

刘博

I'm a slow walker, But I never walk backwards.
首页
技术
常见面试题
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 数据处理与存储类

  • Spring 生态类

  • 缓存问题类

  • 多线程类

  • JVM 类

  • MySQL 类

    • MySQL 为什么一定要有一个主键
    • MySQL 中的 RR 隔离级别,到底有没有解决幻读问题
    • MySQL 的行级锁到底锁的是什么东西?
    • 存储 MD5 值应该用 VARCHAR 还是用 CHAR?
    • 数据库的三范式是什么?
    • 说说 InnoDB 与 MyISAM 的区别
    • drop、truncate、delete 的区别
    • 聊一聊数据库事务机制
    • 聊一聊 MySQL 中的关联查询
    • 事务隔离级别有哪些?MySQL 的默认隔离级别是什么
    • 分库分表之后,id 主键如何处理?
    • 说说在 MySQL 中一条查询 SQL 是如何执行的?
    • 讲解下 DDL、DML、DCL
    • 存储过程和触发器的作用
    • MySQL 如何行转列和列转行
    • 如何查看 SQL 的执行计划
    • union 和 unionAll 的区别
    • having 和 where 的区别
    • 常见的索引原则
    • MySQL 中的 IN 和 EXISTS 子句有什么区别?
    • MySQL 如何处理 NULL 值,对性能有什么影响?
    • 如何在 MySQL 中处理和避免全表扫描?
      • MySQL 中的表空间是什么,它的作用是什么?
      • 在 MySQL 中,如何优化 ORDER BY 查询?
    • Java 8 + 特性类

    • 其他技术类

    • 常见面试题
    • MySQL 类
    刘博
    2025-12-29
    目录

    如何在 MySQL 中处理和避免全表扫描?

    全表扫描(Full Table Scan)是指 MySQL 查询时未使用索引,逐行扫描表中所有数据,性能极差(百万级数据需几秒甚至几分钟),处理和避免方案如下:

    # 1. 识别全表扫描

    通过EXPLAIN命令查看执行计划,若出现以下情况,说明是全表扫描:

    • type=ALL(访问类型为全表扫描);
    • key=NULL(未使用任何索引);
    • rows值接近表的实际行数(预估扫描行数等于表行数)。

    # 2. 避免全表扫描的核心方案

    • 1. 为查询字段创建合适的索引:
      • 为WHERE子句的过滤字段创建索引(如WHERE age > 20,创建idx_age);
      • 为JOIN关联字段创建索引(如user.id = order.user_id,创建order表的idx_userid);
      • 为ORDER BY/GROUP BY字段创建索引(如ORDER BY create_time,创建idx_create_time);
      • 避免过度索引,优先创建联合索引(覆盖多个查询场景)。
    • 2. 优化查询 SQL,避免索引失效:
      • 避免在索引字段上做函数操作(如DATE(create_time)='2024-01-01'改为create_time BETWEEN '2024-01-01 00:00:00' AND '2024-01-01 23:59:59');
      • 避免使用!=、<>、NOT IN、IS NULL(改为BETWEEN、IN、IS NOT NULL的替代方案);
      • 避免模糊查询前缀通配符(如LIKE '%张三'改为LIKE '张三%');
      • 避免字符串与数字比较(如phone=13800138000改为phone='13800138000')。
    • 3. 控制表的数据量,拆分大表:
      • 水平分表:将大表按分表键拆分(如用户表按user_id%8分 8 张表),减少单表数据量(每张表数据量控制在 100 万以内);
      • 垂直分表:将大表的冷热数据拆分(如用户表的基本信息和历史订单拆分到两张表),减少查询时扫描的数据量。
    • 4. 优化查询条件,减少扫描范围:
      • 避免SELECT *,只查询需要的字段(减少数据传输和内存消耗);
      • 增加过滤条件,缩小查询范围(如WHERE create_time > '2024-01-01',过滤旧数据);
      • 使用LIMIT限制返回结果(如LIMIT 10,找到匹配数据后立即终止查询)。
    • 5. 优化 MySQL 配置,提升全表扫描性能(临时方案):
      • 增大innodb_buffer_pool_size(让更多数据缓存到内存,全表扫描时从内存读取,而非磁盘);
      • 关闭query_cache(MySQL 8.0 已移除),避免缓存失效带来的额外开销;
      • 优化innodb_read_io_threads(增加 IO 线程数,提升磁盘读取速度)。

    # 3. 必须全表扫描的场景及优化

    部分场景无法避免全表扫描(如SELECT COUNT(*) FROM user、SELECT * FROM user WHERE name LIKE '%张三%'),可通过以下方式优化:

    • COUNT (*) 优化:
      • MyISAM 表:COUNT(*)直接返回存储的总行数,性能优;
      • InnoDB 表:避免COUNT(*)(需扫描全表),改为维护计数器表(如user_count表,记录总行数,新增 / 删除用户时更新计数器);
    • 模糊查询优化:
      • 若需LIKE '%张三%',可使用全文索引(FULLTEXT INDEX),查询时用MATCH AGAINST(如SELECT * FROM user WHERE MATCH(name) AGAINST('张三'));
      • 用 Elasticsearch 替代 MySQL,处理全文检索场景。

    上次更新: 12/30/2025
    MySQL 如何处理 NULL 值,对性能有什么影响?
    MySQL 中的表空间是什么,它的作用是什么?

    ← MySQL 如何处理 NULL 值,对性能有什么影响? MySQL 中的表空间是什么,它的作用是什么?→

    最近更新
    01
    CPU 使用率较高排查和解决
    12-29
    02
    JVM OOM 问题如何排查和解决
    12-29
    03
    接口防刷怎么实现?
    12-29
    更多文章>
    Theme by Vdoing | Copyright © 2025-2026 Bohr-L's note
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式