SQLite:创建多个索引,多个索引列与单个索引,哪一个有助于获得最佳性能?

时间:2016-01-09 10:06:57

标签: mysql performance sqlite indexing

我有一张这样的表:

CREATE TABLE `ng1` (
    `word1` TEXT NOT NULL,
    `kd`    TEXT NOT NULL,
    `kd1`   TEXT NOT NULL,
    `kd2`   TEXT,
    `kd3`   TEXT,
    `dt`    INTEGER DEFAULT '0',
    `dm`    INTEGER DEFAULT '0',
    `freq`  REAL DEFAULT '0',
    `lastused`  INTEGER DEFAULT '0',
    PRIMARY KEY(word1)
);

我有这些类型的查询:

SELECT * FROM ng1 WHERE kd='abc' ORDER BY freq DESC
SELECT * FROM ng1 WHERE kd1='a' AND dt='1' ORDER BY freq DESC
SELECT * FROM ng1 WHERE kd2='ab' AND dt='1' AND dm='1' ORDER BY freq DESC
SELECT * FROM ng1 WHERE kd3='abc' AND dt='1' AND dm='1' ORDER BY freq DESC
SELECT * FROM ng1 WHERE kd3='abc' AND word1 LIKE 'abc%' AND dt='1' AND dm='1' ORDER BY freq DESC

那么什么样的指数可以帮助我获得最佳表现呢?

  1. 为我需要在查询中使用的每个字段创建多个索引 - - index1:kd

    • index2:kd1
    • index3:kd2 ....以及用于kd3,dt,dm,freq字段的索引
  2. 创建具有多列的多个索引:

    • index1:kd,freq
    • index2:kd1,freq
    • index3:kd2,freq
    • index4:kd3,freq
    • index5:kd3,dt,dm,freq
  3. 创建包含多列的单个索引:

    • index1:kd,kd1,kd2,kd3,dt,dm,freq

1 个答案:

答案 0 :(得分:0)

这些评论适用于MySQL。

首先,您无法索引TEXT 。您可以将VARCHAR索引到某个限制(通常为255)。因此,在可行的情况下,将TEXT更改为合理的长度VARCHAR(n)

让我们看看您的示例

SELECT * FROM ng1 WHERE kd='abc' ORDER BY freq DESC
SELECT * FROM ng1 WHERE kd1='a' AND dt='1' ORDER BY freq DESC
SELECT * FROM ng1 WHERE kd2='ab' AND dt='1' AND dm='1' ORDER BY freq DESC
SELECT * FROM ng1 WHERE kd3='abc' AND dt='1' AND dm='1' ORDER BY freq DESC

这四个基本上都是一样的:WHERE只有'='并在一起。因此,以任何顺序启动具有这些变量的复合索引。由于您完成了WHERE并且没有GROUP BY,因此您可以转到ORDER BY。将freq添加到最后。例如,最后一个需要

INDEX(kd3, dt, dm, freq) or
INDEX(dm, dt, kd4, freq) or ...

这种情况因 LIKE

而有所不同
SELECT * FROM ng1 WHERE kd3='abc' AND word1 LIKE 'abc%' AND dt='1' AND dm='1' ORDER BY freq DESC

没有前导通配符的LIKE被视为“范围”,有点像word1 >= 'abc' AND word1 < 'abd'。与ORDER BY一样,范围将是索引中使用的 last 列。所以,你能做的最好的是:

INDEX(kd3, dt, dm, word1)

前3个可以按任何顺序排列,但word1必须在之后。添加freq将毫无用处。

我在Index Cookbook中讨论了这个问题。

因此,在您的示例中,5 SELECTs的5个不同索引是最佳的。无论出于何种原因,如果您想最小化索引数量,这里有两种方法:

有时优化程序会很乐意跳过WHERE并使用索引ORDER BY 。在这种情况下,INDEX(freq)对所有人来说都会“总比没有好”。

你的问题暗示了一些“巩固”。我建议INDEX(dt, dm, kd3)按照这个顺序处理最后4 SELECTs“比没有好”。 dt必须是#2的第一名。添加了kd3,因为它有助于#4和#5。

其他说明......

NULL / NOT NULL 并不重要。

PRIMARY KEY(word1) “总比没有好”,但只适用于#5。并且,根据基数,可能优先于我建议使用

编写操作INSERTDELETE,有时UPDATE)会因为拥有大量索引而变慢。但是,通常SELECTs的好处超过了这一点。因此,只要您不“索引每一列”,就不要担心索引的数量。