› MySQL 5.5 Community Server
› MySQL 5.6 Community Server
› Percona Configuration Wizard
› XtraBackup 搭建主从复制
Great Sites on MySQL
› Percona
› MySQL Performance Blog
› Severalnines
推荐管理工具
› Sequel Pro
› phpMyAdmin
推荐书目
› MySQL Cookbook
MySQL 相关项目
› MariaDB
› Drizzle
参考文档
› http://mysql-python.sourceforge.net/MySQLdb.html
zealinux
V2EX  ›  MySQL

MySQL 该不该给 status 添加索引?

  •  
  •   zealinux · Apr 28, 2020 · 7589 views
    This topic created in 2389 days ago, the information mentioned may be changed or developed.

    现在某个表,有个 status,有两个值,0,1

    按照好多文档说明,这列不应该加索引。

    比如,0 是未处理的,1 是处理过的。

    一般都是要查 0,来进行处理。

    发现 status 加了索引之后,查找的速度飞快。

    2000w 的表,SELECT COUNT(*), 从 14s 下降到 0.1s 以下( SQL_NO_CACHE )

    28 replies  •  2023-08-25 21:45:37 +08:00
    yemoluo
    yemoluo
    Apr 28, 2020
    1
    加了索引,`select count(*)` 走的是索引,索引比起原表那真是小太多了
    gotonull
    gotonull
    Apr 28, 2020
    2
    status 加索引对 count 有影响?不懂,插眼。等一个大佬解释
    virusdefender
    virusdefender
    Apr 28, 2020
    3
    status 加索引对 count 有影响?+1

    看下 explain 的结果
    yumenawei
    yumenawei
    Apr 28, 2020
    4
    这个是特例。
    你随便查点需要回表的数据试试。
    sadfQED2
    sadfQED2
    Apr 28, 2020 via Android
    5
    Count 操作不会回表,你试试 select *
    xuanbg
    xuanbg
    Apr 28, 2020
    6
    这种看情况,索引就是使无序的数据变得有序,相当于让乱糟糟的一群人按某种特性排起了整齐的队伍。如果你需要找的人在队伍里面占大多数,那这个队伍没多大意思。如果你要找的是队伍里面的少数人,那效率提升就是杠杠的。
    xinshoushanglu
    xinshoushanglu
    Apr 28, 2020
    7
    count 应该是在 mysql.sys 表里记录的一个量,和数据表的规模没关系。我之前一张一千多万的表,查都查不动,但是 count(1)或者 count(*) 还是秒出
    encro
    encro
    Apr 28, 2020❤️2
    8
    索引对于量少的数据有效。

    比如你表数据绝大部分都是 status=0 的,
    但是你查询是 status=1 的数据,这时候索引有效的,也是很快的,
    如果你查 status=0,因为数据量超过了总数一般,那么索引无效。
    glacer
    glacer
    Apr 28, 2020
    9
    加索引有效的原因是 0 和 1 的数据量不均等吧。如果 0 只占很小一部分,status=0 的时候当然很快
    PopRain
    PopRain
    Apr 28, 2020
    10
    @xinshoushanglu 人家是做条件 count, 不是统计全表的行数。 状态值用索引快是因为一个 Page 可以保存更多的记录,就算走索引全扫描,所需要的 I/O 比表扫描也少的多
    orcusfox
    orcusfox
    Apr 28, 2020 via iPhone
    11
    区分度不大的字段加索引效果不大吧
    wdlth
    wdlth
    Apr 28, 2020
    12
    应该与其他的字段一起加联合索引,单独加不一定能用上。
    gongwenhua
    gongwenhua
    Apr 28, 2020
    13
    截个图看看 explain ?
    daozhihun
    daozhihun
    Apr 28, 2020
    14
    不建议加索引,筛选的行数太少,系统很可能会忽略掉
    cheng6563
    cheng6563
    Apr 28, 2020
    15
    这算是个特殊用法吧
    jam1024
    jam1024
    Apr 28, 2020
    16
    建议加组合索引,不建议加单独索引
    Orenoid
    Orenoid
    Apr 28, 2020 via Android
    17
    status 这种选择性很低的列,单独加索引收益很低
    love
    love
    Apr 28, 2020
    18
    这个状态很少的列要看数据分布的。如果是分布很平均就不用加。
    dongisking
    dongisking
    Apr 28, 2020
    19
    不建议,建议分表
    uxff
    uxff
    Apr 28, 2020
    20
    加索引快是因为直接读索引就能统计到条数。而不需要再读表内容,减少了 io 次数。不加索引会增加额外的 io 开销。
    读完索引再读表内容一般至少多加一次 io,除非表很小(在 B+数的一簇以内)。
    如果不加索引,且 status=0 的值很多,分散在不同的簇上,那就很慢,需要很多次 io 。
    uxff
    uxff
    Apr 28, 2020
    21
    看了 mysql 的实现原理后,你就懂了,mysql innodb 索引是针对现代磁盘高度优化的。只统计或查询索引上的字段都会快很多。
    littlewing
    littlewing
    Apr 28, 2020
    22
    count(*) count(1) count(status) 确实是有用的,因为 MySQL 判断扫描 status 索引也能得到正确的 count,而 status 索引比其他索引和主键索引扫描起来快多了
    但是如果想用 status 索引加快 select * from xxx where status = 1 这样的查找速度的话,就不用想了,MySQL 绝对会选择扫描主键索引,因为 cardinality 太小了,再加上回表的开销,MySQL 会认为走主键索引更快
    littlewing
    littlewing
    Apr 28, 2020
    23
    @xinshoushanglu innodb 是不能这样做的,因为有事务和隔离级别的存在,同一时间不同事务看到的 count 可以不一样,Myisam 是可以这样做的
    hooopo
    hooopo
    Apr 29, 2020
    24
    具体情况具体分析
    thinkmore
    thinkmore
    Apr 29, 2020
    25
    不建议加。status 区分度太低了,基本全是扫描叶子节点。

    如果你查这样的,你就能感受到了

    select column_1,column_2,column_3 from table where status = 1
    qyvlik
    qyvlik
    Apr 29, 2020
    26
    根据业务要求加,就是根据哪种 sql 查询多的去加索引,还要根据具体 sql 查询拼接的条件。
    所谓 status 区分度低的前提是 0,1 均匀分布,说白了可能各 50%,这样加索引就没啥效果。按照你的问题描述,以及可能的常用场景,0 和 1 的分布不是均匀的,一般是 0 >> 1,就是说 status 为 0 可能就是全表记录的 一小部分(例如 1%),那么如下的查询 sql:
    select * from table where status = 0
    就会走索引,而且索引扫描的行数也不会太多。
    但是如下的 sql:
    select * from table where status = 1,可能会走索引,但是扫描的行数过多时会让 mysql 做出扫描全表的执行计划。
    select count(*) from table,在有索引的情况,可能会走索引,具体看看执行计划。
    54qyc
    54qyc
    Aug 25, 2023
    27
    status 如果是和常量值比较,并且常量值占比比较小,则 mysql 会走索引而不会全表扫描. 这里和 count 机制没关系吧,select 任意的速度应该都会更快。OP 是这样吗?
    54qyc
    54qyc
    Aug 25, 2023
    28
    @littlewing 并不是这样。与常量比较,mysql 会看 1 的占比。占比低就会走索引。而不是看基数,看基数发生在与列值比较的情况。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   4741 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 85ms · UTC 03:21 · PVG 11:21 · LAX 19:21 · JFK 22:21
    ♥ Do have faith in what you're doing.