索引具有重复值的列

Indexing a column having duplicate values

考虑这些 table:

seed (seedid, seedname) # PK-(seedid) 
stock (seedid, stk, storeid)  # PK-(seedid,storeid), FK-(storeid)
#InnoDB

stock: 
      seedid, stk, storeid
         1    12     81
         2    13     81
         3    14     81

         1    12     82
         2    11     82
         3    13     82
         4    12     82

Query -> select stk from stock where seedid = 'aaa' and storeid = 'yyy'.

Tablestock代表几家店铺的库存,所以storeid会重复过来。

如何索引,table stock,因为它会经常使用 storeid 查询?

主键自动索引,既然(seedid,storeid)已经是主键了,是不是不需要再索引了?

如果seedid,storeid设置为主键,那么它已经有一个唯一索引。 但是,查询一次只能使用一个索引。因此,如果您定期查询 'where seedid=3 and storeid=5' 之类的内容,则会使用该索引。但是如果你只是使用 'where storeid=5' 它可能不会使用索引。 (您可以在查询前使用 'explain' 来查看 mysql 将使用哪些索引。)

所以基本上您需要一个索引来覆盖您需要在 where 子句中定期查询的列。

根据不完整的规范,我会这样做:

   CREATE UNIQUE INDEX stock_UX1 ON stock (storeid,seedid,stk)

该索引将满足以 storeid 作为前导列的索引的要求。 (而且我们知道如果这是 InnoDB 并且 storeid 是外键,将会有这个要求。)

对于如此短的 table 行,我会继续将其设为覆盖索引,并包括所有列。然后可以直接从索引页面满足查询,而无需查找底层 table.

中的数据页面

因为我们知道 (seedid,storeid) 是唯一的(作为 PRIMARY KEY 给出),我们知道 (storeid,seedid) 也是唯一的,所以我们不妨将索引声明为 UNIQUE。


还有其他选择;我们不必在上面创建该索引。我们可以这样做:

   CREATE INDEX stock_IX2 ON stock (storeid)

但这将使用几乎相同数量的 space,并且对尽可能多的查询没有好处。


二级索引将包含table的主键;因此第二个索引将包含 seedid 列,给定 table 的 PRIMARY KEY。即索引等同于:

   CREATE INDEX stock_IX3 ON stock (storeid,seedid)

而且我们知道这两列的组合是唯一的,因此我们可以包含 UNIQUE 关键字

   CREATE UNIQUE INDEX stock_UX4 ON stock (storeid,seedid)

如果我们对

形式的查询进行解释
  EXPLAIN
  SELECT t.storeid
       , t.seedid
       , t.stk 
    FROM stock t 
   WHERE t.storeid = 'foo'

我们很可能会在二级索引上看到范围扫描操作;但是检索 stk 列的值将需要查找基础 table 中的数据页。在二级索引中包含 stk 列将使该索引成为查询的 覆盖 索引。使用答案中首先推荐的索引,我们期望 EXPLAIN 输出显示 "Using index".