【问题标题】:Mysql Index is not workingMysql 索引不起作用
【发布时间】:2014-09-15 12:08:53
【问题描述】:

谁能告诉我为什么mysql没有使用'playerLead_status_INDEX'索引?

CREATE TABLE `bcs_player_lead`(
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `first_name` varchar(100) DEFAULT NULL,
  `last_name` varchar(100) DEFAULT NULL,
  `email_id` varchar(100) DEFAULT NULL,
  `city` varchar(100) DEFAULT NULL,
  `state` varchar(100) DEFAULT NULL,
  `country` varchar(100) DEFAULT NULL,
  `created` datetime DEFAULT NULL,
  `status` int(11) DEFAULT NULL COMMENT '1-New,2-invitation send',
  PRIMARY KEY (`id`),
  KEY `playerLead_status_INDEX` (`status`)
) ENGINE=InnoDB AUTO_INCREMENT=510 DEFAULT CHARSET=latin1;

解释选择 email_id,id,NULL,first_name,last_name,NULL,state,city,NULL,(2) 作为类型 FROM bcs_player_lead WHERE status='1'

id|select_type|table |type|possible_keys |key |key_len |ref |rows |Extra
1 |简单 |bcs_player_lead |全部 |playerLead_status_INDEX|{null}|{null}|{null}|第458章

bcs_player_lead 有两个键 -

  1. ID 上的 PRIMARY
  2. playerLead_status_INDEX 状态

提前致谢!

【问题讨论】:

  • 不确定您使用的 MySQL 版本,但考虑到您的状态为 'DEFAULT NULL' 可能是个问题。我在 MySQL 站点 dev.mysql.com/doc/refman/5.5/en/create-table.html 上找到了这个@“在 MySQL 5.5 中,只有 InnoDB、MyISAM 和 MEMORY 存储引擎支持对可以具有 NULL 值的列的索引。在其他情况下,您必须将索引列声明为 NOT NULL 或错误结果.".我唯一能想到的。
  • "...有时 MySQL 不使用索引,即使索引可用。这种情况发生的一种情况是优化器估计使用索引将需要 MySQL 访问一个非常大的百分比表中的行数。(在这种情况下,表扫描可能会快得多,因为它需要的搜索次数更少。)...”参见dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
  • 这可能是@Leo 所说的情况,并且情况是表统计信息未更新。
  • 只是检查,尝试将 LIMIT 添加到您的查询(可能是 LIMIT 1000)=> "...但是,如果这样的查询使用 LIMIT 仅检索某些行,MySQL 无论如何都会使用索引,因为它可以更快地找到要在结果中返回的几行。..."
  • Abhi,使用force index 只是一个检查。在您的情况下,因为它只获取 500 行,即使它不进行索引搜索,您也不会感到任何渣滓。

标签: mysql indexing


【解决方案1】:

查询规划器计算执行给定查询的多个路径的成本。选择成本最低的路径。使用索引扫描 VS 表扫描是 2 条路径。 让我们考虑两条路径:

  1. 由于您有一个关于状态的索引并且还试图检索其他列,因此您的索引不是覆盖索引。因此,当一个键满足 where 子句时,innodb 需要从磁盘读取该行的数据(因为索引本身没有它)。 “状态”字段似乎只有 2 个值。对于这两个值中的任何一个,很多行都符合条件。例如:如果识别出 1k 行,这意味着从磁盘中随机读取 1k 次
  2. 假设您的表有 10k 行。如果使用表扫描,则意味着扫描并读取表的所有页面。但这些大多是顺序读取。

因此,案例 1 可能比案例 2 产生更多的成本。您应该检查索引基数以对此有所了解。通常,具有非常低基数和非常低选择性的索引是不好的选择,即唯一值非常低(状态)并且实际行数非常高。

【讨论】:

    【解决方案2】:

    我不是 DBA 但 AFAIK,有时即使有一个索引也不会使用:当表统计信息未更新(或)时,@Leo 所说的要检索的行数可能会更少(因为在你的情况下只有 458 行检索)。

    您可以在查询中使用FORCE INDEX (index_name) 强制使用索引。试试看EXPLAIN PLAN

    SELECT email_id,id,NULL,first_name,last_name,NULL,state,city,NULL,(2) as type 
    FROM bcs_player_lead 
    FORCE INDEX (playerLead_status_INDEX)
    WHERE status='1'
    

    您可能想查看此帖子一次MySQL not using indexes with WHERE IN clause?

    【讨论】:

    • 是的,我认为它没有考虑索引,因为记录较少。谢谢
    猜你喜欢
    • 2013-03-07
    • 2011-04-30
    • 2016-11-18
    • 1970-01-01
    • 2011-04-06
    • 2018-01-19
    • 2017-01-27
    • 1970-01-01
    相关资源
    最近更新 更多