分类字段是否需要建立索引? (MySQL或MongoDB)

时间:2013-07-07 12:24:22

标签: mysql mongodb indexing

对于一个表(比如'food'),有一个带有潜在值[1,2,3,4]的列'type',它指定了该条目的类型(例如fruit)。正如我所期待的那样选择

SELECT name FROM food WHERE type = 3 ;    

最常被调用,我想在这种情况下会推荐一个索引。由于该字段可能只有少数值,我想知道索引是否有用。(同样对于MongoDB?)

2 个答案:

答案 0 :(得分:2)

这样一个字段的索引可能在MySQL中没用。实际上,这样的索引可能会使大多数查询变得更糟。

有一种情况,索引总是会更快。这是使用索引中的列的查询,例如:

select count(type)
from food
where type = 3;

这更快,因为读取索引应该比读取表更快,因为数据更小(可能,您可以包括索引中的所有列)。

在其他情况下,MySQL在表可用时会使用索引。

您要问的问题是关于指数的“选择性”。考虑一下您的问题:

SELECT name
FROM food
WHERE type = 3 ; 

如果所有行都有type = 3,那么您必须读取所有匹配的记录(以获取name的值)。如果每页有一条记录,则索引可能对您有所帮助,因为它减少了页面读取次数。更现实的情况是页面包含100条记录。然后,如果25%的记录具有相同的类型,则典型页面上将有25个这样的记录。基本上,每个页面仍然必须被阅读。问题是页面是按顺序读取(“全表扫描”)还是通过索引读取。

这两种读表方式有所不同。在全表扫描中,页面是按顺序读取的,一旦读取页面,就不会再次访问它。在索引读取中,页面随机读取,一次读取一个记录,页面可以多次读取。在极端情况下,页面不适合页面缓存,并且同一页面被刷新到磁盘并对页面上的每个记录一次又一次地读取。非常低效。

通过在type, name上建立索引,可以提高此查询的效率。

所以,你的问题的答案是要小心索引,特别是对于大表。如果在分类列上有索引,请将其设置为复合索引,这样只能使用索引来满足查询,而不必返回数据页。

答案 1 :(得分:2)

索引不太可能有用,但您应该使用查询和数据对其进行测试。如果列具有很少的不同值,则查询将返回表的行的相当大的部分,并且读取索引相当于全表扫描。实际上,全表扫描甚至可能比读取索引更快。

如果在其他查询中使用该行的类型,则可能有助于将该类型作为多列索引的一部分。