索引具有重复值的列
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".
考虑这些 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".