3

我在 MySQL 中有一个查询(用于存储过程),它按名称和另一个字段进行搜索。当我使用这些搜索参数的不同组合时,我会得到快速的结果(在 1 到 2 秒之间),但对于一些特定的值,我会得到一个需要 9 秒才能在生产网站上返回结果的查询。以下是我从 EXPLAIN 语句中得到的:

id, select_type, table, type, possible_keys, key,       key_len, ref,   rows, Extra
--------------------------------------------
1,  SIMPLE,      Names, ref,  IX_Name,       IX_Name,   17,      const, 3173, Using where

名称被声明为 varchar(40),另一个字段是 Unsigned smallint(6)。我在查询中使用的名称 (IX_Name) 的前 15 个字符上使用索引。我可以看到,慢查询会在 EXPLAIN 输出的“行”列中检查大量行。

我不确定我能做些什么来提高性能。上面的 EXPLAIN 输出有什么明显的错误吗?

谢谢,蒂姆

4

4 回答 4

3

你是如何填充表格的?索引是树形结构,为了有效地工作,它们需要平衡——如果表被批量加载或应用定期维护,这将自动发生。如果这些都不正确,那么索引对于树中过度增长的那些部分的效率将大大降低。

最简单的检查是删除索引并重新创建它。如果您之后有相同的行为,那是另一回事,但至少这是消除了一种可能性。

于 2009-08-15T09:11:39.757 回答
2

您的查询似乎只使用一个字段的索引。您提到您按名称和“另一个字段”搜索。MySQL(在特定情况下的最新版本除外)仅限于查询中每个表出现一个索引。这意味着,如果您在 name 和另一个字段上都有索引,MySQL 可能不得不猜测哪个索引最有帮助并忽略另一个。似乎更好的查询结构或索引定义会有所帮助。如果您的名字非常独特,并且您在解释计划中获得了 3,000 行,那么要么数据库中的元数据不好,要么您在另一个领域有很多其他可能性。

您可以发布表的查询和架构吗?

对于同一个 SQL,您的查询总是快还是慢?即,如果您搜索Fisher,有时它会很快,有时会很慢,或者它们是否一致。如果它们一致,则可能是由于 CPU 或磁盘活动所致。如果可变,则可能是由于数据库上的其他查询。

此外,根据您选择的内容,如果您可以将完整结果放入索引中,那么您的查询将会运行,因为它不必敲击磁盘来验证记录。我在“使用索引”查询方面有了相当惊人的改进。

雅各布

于 2009-08-16T05:12:28.603 回答
1

好的,您在前缀上有一个索引。您使用了前 15 个字符,但假设您只使用了 1 个字符,并且您的表具有以下名称值:

Al Barb Beth Betsy Bill Biff Bob Bonny Buck Bud Carl

由于我的索引仅在第一个字符上,数据库必须读取索引返回的所有行,并将每个完整名称与谓词进行比较。

现在,如果我寻找“Al”,我的索引会返回一行。然后我将谓词中的“Al”与行中的“Al”进行比较,我有一个匹配项,所以我返回该行,我就完成了。

现在,如果我寻找“亚历克斯”,我的索引会返回一行。然后我将谓词中的“Alex”与行中的“Al”进行比较,我没有匹配项,也没有更多潜在匹配项,我就完成了。

但是,如果我查找“Bud”(或以“B”开头的任何内容),我的索引会返回 9 行。在完成之前,我需要阅读九行并与谓词进行比较。

做这个:

select substring( name, 1, 15), count(*)
from names
group by substring( name, 1, 15);

我想你会发现你的快速查找是独一无二的,而慢速查找是许多名称共享一个共同前缀的地方。

于 2009-08-15T09:42:08.573 回答
0

假设您想将它们呈现给用户,我发现 3173 行可以考虑一个相当大的数字。如果检索到的实际记录数大大减少,则应考虑创建更多索引。了解 EXPLAIN 报告不同搜索词的内容会很有用。

于 2009-08-15T15:00:45.773 回答