我遇到了一个我想了解的有趣问题。我有一张桌子:
`id` BIGINT(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` BIGINT(20) unsigned NOT NULL,
`followers_count` INT(10) unsigned NOT NULL DEFAULT 0,
`friends_count` INT(10) unsigned NOT NULL DEFAULT 0,
`statuses_count` INT(10) unsigned NOT NULL DEFAULT 0,
`favourites_count` INT(10) unsigned NOT NULL DEFAULT 0,
`listed_count` INT(10) unsigned NOT NULL DEFAULT 0,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
我执行以下查询:
SELECT
followers_count
,friends_count
,statuses_count
,favourites_count
,listed_count
,UNIX_TIMESTAMP(DATE(created_at
))AS {{1} } FROMid
WHEREuser_track
> = DATE_SUB(NOW(),INTERVAL 14 DAY)和created_at
='1234567'
1:在该表上使用以下索引,查询需要几分钟才能完成:
INDEX
user_id
(user_numbers
,created_at
,user_id
,followers_count
,friends_count
,statuses_count
,{{1} })
用上面的索引1解释查询:
favourites_count
2:但是,使用该表上的以下索引,它需要不到200毫秒:
INDEX
listed_count
(id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE user_track range user_numbers user_numbers 12 NULL 1119318 Using where; Using index
,user_report
,user_id
,id
,created_at
,followers_count
,{{1} },friends_count
)
用上面的索引2解释查询:
statuses_count
通过解释查询,我看到第一个索引导致扫描很多行,而第二个索引有“ref:const”,只扫描了几行。但我想了解为什么会发生这种情况。
答案 0 :(得分:2)
如the manual中所述:
如果表具有多列索引,则优化程序可以使用索引的任何最左前缀来查找行。例如,如果您在
(col1, col2, col3)
上有一个三列索引,则您已在(col1)
,(col1, col2)
和(col1, col2, col3)
上编制了索引搜索功能。如果列不构成索引的最左前缀,则MySQL无法使用索引执行查找。假设您在此处显示
SELECT
语句:SELECT * FROM tbl_name WHERE col1=val1; SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2; SELECT * FROM tbl_name WHERE col2=val2; SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
如果
(col1, col2, col3)
上存在索引,则只有前两个查询使用索引。第三个和第四个查询确实涉及索引列,但(col2)
和(col2, col3)
不是(col1, col2, col3)
的最左前缀。