我有一个具有以下结构的表meta
(这只是一个非规范化数据的示例)
`id` int(3) not null auto_increment primary key,
`category_id` int(3),
`subdomain` varchar(191),
`created_at` timestamp,
`updated_at` timestamp
subdomain
字段可以存储唯一值,并且像“通用”这样的重复值可以重复多次
情况1
我也有一个索引subdomain
。该索引适用于查询
Select `id` from `table` where `subdomain` = 'general'
但是当我尝试获取一些非索引字段时,mysql会扫描所有表,并且不使用索引
Select `created_at` from `table` where `subdomain` = 'general'
据我所知,Inno-db非聚集索引存储对行的引用,因此无需对所有行执行线性搜索即可检索某些字段。
我也知道优化器可以为人类选择一个意外的计划,但是在这种情况下原因可能是什么?
无论表中有多少数据,结果始终相同。
答案 0 :(得分:1)
当索引支持的过滤不是选择性很差 /您要过滤的值具有高基数时,就会发生这种情况。这意味着您的总行中有很大一部分与索引支持的条件匹配(例如,您的行中有90%与subdomain = 'general'
匹配)。如果在这种情况下使用索引,则与全表扫描相比,最终将处理更多数据。
示例:您有100行,其中90行与subdomain = 'general'
相匹配。
全表扫描需要访问所有100行以检查条件,并读取90个值。
索引支持的select需要访问满足条件的索引中的90个项目,并按照指针从索引到实际行的顺序从该行中选择未索引的值。最终在索引上进行90次查找+从行中读取90条= 180次操作。这比全表扫描要慢,在全表扫描中,您只需要访问一些行即可。这些操作的成本可能不一样,但是最终最终您需要做更多的工作。