我有一张这样的表:
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
那么什么样的指数可以帮助我获得最佳表现呢?
为我需要在查询中使用的每个字段创建多个索引 - - index1:kd
创建具有多列的多个索引:
创建包含多列的单个索引:
答案 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。并且,根据基数,可能优先于我建议使用
编写操作(INSERT
,DELETE
,有时UPDATE
)会因为拥有大量索引而变慢。但是,通常SELECTs
的好处超过了这一点。因此,只要您不“索引每一列”,就不要担心索引的数量。