请考虑以下表格:
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)
已经是主键了,所以不需要进一步对其进行索引了吗?
答案 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
的输出显示“正在使用索引”。