mysql - 为什么MySQL不使用索引?

标签 mysql indexing

我有两个表:(省略了与这个问题无关的列):

CREATE TABLE 'oc_room' (
  'id' int(11) NOT NULL AUTO_INCREMENT,
  'house_id' int(11) NOT NULL,
  'style_id' int(11) DEFAULT NULL,
  'weight' int(11) DEFAULT '0',
  'state' tinyint(4) DEFAULT '0',
  -- (more columns, omitted for clarity)
  PRIMARY KEY ('id'),
  KEY 'house_id' ('house_id'),
  KEY 'style_id' ('style_id'),
  KEY 'butler_id' ('butler_id'),
  KEY 'oc_room_house_state_hidden_ik_1' ('house_id','state','hidden'),
  CONSTRAINT 'oc_room_ibfk_1' FOREIGN KEY ('house_id') REFERENCES 'oc_house' ('id'),
  CONSTRAINT 'oc_room_ibfk_2' FOREIGN KEY ('style_id') REFERENCES 'oc_room_style' ('id'),
  CONSTRAINT 'oc_room_ibfk_3' FOREIGN KEY ('butler_id') REFERENCES 'oc_butler' ('id')
) ENGINE=InnoDB AUTO_INCREMENT=267 DEFAULT CHARSET=utf8;

CREATE TABLE 'oc_circle_of_community' (
  'id' int(11) NOT NULL AUTO_INCREMENT,
  'circle_id' int(11) NOT NULL,
  'community_id' int(11) NOT NULL,
  PRIMARY KEY ('id'),
  KEY 'circle_id' ('circle_id'),
  KEY 'community_id' ('community_id'),
  CONSTRAINT 'oc_circle_of_community_ibfk_1' FOREIGN KEY ('circle_id') REFERENCES 'oc_circle' ('id'),
  CONSTRAINT 'oc_circle_of_community_ibfk_2' FOREIGN KEY ('community_id') REFERENCES 'oc_community' ('id')
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

当我解释一个选择语句时,我有两个问题

问题一:

让我们从两张图片开始:

图片-1: enter image description here

图片-2: enter image description here 请特别注意 explain 输出的底线。

然后将PIC-1中的表格与PIC-2中的表格进行比较。你会发现:

  1. PIC-1 中 oc_room 的选择使用组合键 oc_room_house_state_hidden_​​ik_1
  2. 那么在PIC-2中,没有用到key。
  3. 两个语句的唯一区别是oc_room.id in (5,7,9,20,40,60 )被替换
oc_room.id in 
   ( select id 
       from oc_house
       where community_id in 
     ( select community_id
         from oc_circle_of_community
        where circle_id in
      ( select id 
          from oc_circle
         where oc_circle.district_id in
         ( select id
             from oc_district
            where oc_district.id = 3 ))))  

为什么不同?

oc_room 总共有大约 300 行。

问题2:

查看表的 PIC-2,第 2 行,它解释了表 oc_circle_of_community 的选择。有两个可能的键:circle_idcommunity_id。为什么这两个键不能用?
(表 oc_circle_of_community 中共有 14 行。这可能会有所帮助。)

最佳答案

来自 bottom 处的手册.

Indexes are less important for queries on small tables, or big tables where report queries process most or all of the rows. When a query needs to access most of the rows, reading sequentially is faster than working through an index. Sequential reads minimize disk seeks, even if not all the rows are needed for the query.

图片-1

a) 300 行对于它来说太小了,无法在单个索引上进行磨练并随后进行扫描,因此它根本不会关心索引,或者

b) 你试图使用一个足够的复合索引,或者

c) 你用 covering index 去拿金牌并避免读取数据页

但是注意,它在 8 行中解决了它,而不是 300。它与复合 (house_id,state,hidden ),最后一个不是你显示的。总共 7 个字节宽。

因为您只有 300 行,analyze table 应该需要一瞬间。它刷新可能变得陈旧的 key 分布的统计数据,从而强制不使用 key 。 key 可能是使用目标,但最终在执行期间被放弃。因此,这是关于其用途的一般性陈述,例如对于大型表格,而不是您的问题。

图片-2

REF NULL 的 14 行与本答案的开头有关。

关于mysql - 为什么MySQL不使用索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32048691/

相关文章:

sql - Postgres 左外连接似乎没有使用表索引

python - Python 中的下划线索引

javascript - chop 不正确的 double (nodejs)

java - 在 HIbernate 中调用存储过程时找不到列 'id'

mysql - 在命令行中使用 R 编写 mysql 的导出过程

mysql - 实现一个mysql数据库来套接字聊天

mysql - 针对 max、count 优化 MySQL InnoDB 查询

mysql - ES + Logstash + MySQL 如何在更新、添加或删除数据时实现索引的实时更新?

php - 从数据库中查找字段为日期时间数据类型的数据

c#-4.0 - 我应该放弃 RavenDB 的整数 Id 吗?