我有下表:
CREATE TABLE Test (
device varchar(12),
pin varchar(4),
authToken varchar(32),
Primary Key (device)
);
在应用程序的不同点,我需要通过不同的 single 列子句查询此表。这意味着我有以下查询:
SELECT * FROM Test WHERE device = ?;
SELECT * FROM Test WHERE authToken = ?;
SELECT * FROM Test WHERE pin = ?;
据我了解,在这种情况下,(device, authToken, pin)
的组合索引毫无意义,因为这只会加快第一个查询的速度,而不会加快第二个或第三个查询的速度。
读取速度比编写该表更重要,因此简单地单独索引每一列是否是这里的最佳解决方案?
答案 0 :(得分:2)
直接的答案是为每个查询创建单独的单列索引:
create index ix1 (device); -- no need to create it since it's the PK.
create index ix2 (pin);
create index ix3 (authToken);
第一个索引(来自PK)使用主索引。第二个和第三个索引可能会变慢,因为它们遭受“第二个索引”缓慢的困扰:它们始终需要先访问第二个索引,然后再访问主索引;如果您选择大量的行,这可能会变慢。
现在,如果您想以SELECT
的速度过高而以修改缓慢(INSERT
,UPDATE
和DELETE
的代价为代价,则可以使用针对每个查询量身定制的“覆盖索引”。这些应该看起来像:
create index ix4 (device, pin, authToken); -- [non needed] optimal for WHERE device = ?
create index ix5 (authToken, device, pin); -- optimal for WHERE authToken = ?
create index ix6 (pin, device, authToken); -- optimal for WHERE pin = ?
注意:如Rick James所言,ix4
与InnoDB表具有的主键索引是多余的。无需创建它。仅出于完整性目的在此处列出。
这些“覆盖索引”仅使用辅助索引,从而根本无需访问主索引即可解决查询。对于大量检索的行,它们要快得多。
答案 1 :(得分:1)
您不需要索引pin列,因为它已经被索引了。对于其他2列(即device和authToken),是的,根据您的共享查询,最好分别对它们进行索引。
请注意,当有大量此类查询命中服务器(该表上也有大量数据集)时,您将看到性能上的显着提高。
答案 2 :(得分:0)
要回答:
“如何为不同的单列子句建立索引表?”
CREATE INDEX Test_device_index ON Test(device);
CREATE INDEX Test_authToken_index ON Test(authToken DESC);
CREATE INDEX Test_pin_index ON Test(pin);
答案 3 :(得分:-1)
这是我建议的模式:
CREATE TABLE Test (
id SERIAL PRIMARY KEY,
device VARCHAR(255),
pin VARCHAR(255),
authToken VARCHAR(255),
UNIQUE KEY index_authToken (authToken),
UNIQUE KEY index_device (device),
KEY index_pin (pin)
);
您有一个id
类型的列,该列不与任何特定数据相关联,并且对UNIQUE
和authToken
具有device
约束。
请记住将WHERE
中使用的任何列都编入索引,并使用以下方法测试覆盖范围:
EXPLAIN SELECT ... FROM Test WHERE pin=?
如果您在计划中看到“表扫描”,那就是缺少索引的问题。
使用VARCHAR(255)
作为默认值也是一个好主意,除非您有非常有说服力的理由对其进行限制。在您的应用程序层中实施长度限制,以后可以轻松地放宽它们。例如,更改为6位数PIN与4位数是一个简单的代码更改,甚至可以逐步推出,这不是架构更改。