索引具有重复值的列

时间:2019-02-20 15:57:19

标签: mysql database-indexes

请考虑以下表格:

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'.

stock代表几家商店的库存,因此storeid将重复出现。

鉴于表stock会经常使用storeid进行查询,我该如何为其编制索引?

自动编入索引的主键,并且由于(seedid,storeid)已经是主键了,所以不需要进一步对其进行索引了吗?

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

基于不完整的规范,我会这样做:

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

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

在表格行很短的情况下,我将其设为覆盖索引,并包括所有列。然后,可以直接从索引页满足查询,而无需在基础表中查找数据页。

由于我们知道(seedid,storeid)是唯一的(给定为PRIMARY KEY),所以我们知道(storeid,seedid)也是唯一的,因此我们最好将索引声明为UNIQUE。


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

   CREATE INDEX stock_IX2 ON stock (storeid)

但这将占用几乎相同的空间,并且对尽可能多的查询没有好处。


二级索引将包含表的主键;因此,给定表的PRIMARY KEY,第二个索引将包含seedid列。也就是说,索引与此等效:

   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列的值,将需要查找基础表中的数据页。在辅助索引中包含stk列将使索引成为查询的 covering 索引。在答案中首先建议使用索引的情况下,我们期望EXPLAIN的输出显示“正在使用索引”。