如何为不同的单列子句建立索引表

时间:2018-10-24 15:21:46

标签: mysql sql indexing

我有下表:

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)的组合索引毫无意义,因为这只会加快第一个查询的速度,而不会加快第二个或第三个查询的速度。

读取速度比编写该表更重要,因此简单地单独索引每一列是否是这里的最佳解决方案?

4 个答案:

答案 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的速度过高而以修改缓慢(INSERTUPDATEDELETE的代价为代价,则可以使用针对每个查询量身定制的“覆盖索引”。这些应该看起来像:

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类型的列,该列不与任何特定数据相关联,并且对UNIQUEauthToken具有device约束。

请记住将WHERE中使用的任何列都编入索引,并使用以下方法测试覆盖范围:

EXPLAIN SELECT ... FROM Test WHERE pin=?

如果您在计划中看到“表扫描”,那就是缺少索引的问题。

使用VARCHAR(255)作为默认值也是一个好主意,除非您有非常有说服力的理由对其进行限制。在您的应用程序层中实施长度限制,以后可以轻松地放宽它们。例如,更改为6位数PIN与4位数是一个简单的代码更改,甚至可以逐步推出,这不是架构更改。