0

我正在学习如何使用索引进行适当的查询优化。假设我有一个巨大的产品表,其中包含每种产品的各种详细信息,例如价格、类别、购买数量、平均评论等等。当有多个“where”条件时,我了解到最好按照它们出现的顺序在“where”条件的任何内容上放置一个多列索引。

但是,如果有这么多用于不同目的的查询,并且如果用户可以选择如何过滤产品表,我很难弄清楚如何扩展它。例如,用户可以浏览产品WHERE rating > 4 AND purchases > 100,也可以是WHERE category = 'x' AND price < 100 AND price > 20。如果选择要过滤的列是随机的,那么适当的多列索引将如何工作?

4

1 回答 1

1

我了解到,无论您的“位置”条件是什么,最好按照它们出现的顺序放置一个多列索引。

你学会了……不完全正确。

子句中出现的顺序WHERE没有意义,因为优化器可以自由地以任何逻辑上有效的方式评估条件,当然要服从表达式中的括号和逻辑运算符(ANDOR等)。

多列索引中的列顺序很重要,因为从左到右,只要在索引中遇到 where 子句中未提及的列,就不能再使用该索引右侧的更多内容。

如果 3 列 (a,b,c) 被索引,并且查询是,WHERE a = 1 AND c = 6那么优化器将只能使用该索引中最左边的“a”列值,而不是“c”。

在这种情况下,它可能仍会选择使用索引来查找 a = 1 的行,然后扫描所有已识别的行以仅查找 c = 6 的行。

您可以将多列索引可视化为多维数组。如果没有已知的值或范围,您需要匹配第一列 (a),第二列 (b) 的值是无意义的、无序的混乱数据,因为它们按“'a'组”排序。 ..您必须遍历每个“a”以找到匹配的“b”值,并遍历每个“a,b”以找到匹配的“c”值。由于在上面的示例中,“b”值是“anything”,因为它没有被指定,“c”值的排序对于优化查询是没有意义的并且不可访问(尽管当SELECTlist 在单个索引中可用,优化器可能会扫描索引而不是扫描整个表,将其视为“覆盖索引”,这通常比全表扫描要好,但仍然不是最佳的)。

如果您的WHERE子句包含两个单独索引的列,优化器将检查索引统计信息并尝试使用最有可能产生最少匹配项的列...如果“a”和“c”各有一个索引,并且索引统计信息表明“c”(高基数)有很多值,但“a”(低基数)只有少数值,优化器通常会使用“c”上的索引来查找匹配的行,然后扫描所有这些行以获取“a”的请求值。

或者,它可能会尝试使用两个索引的并集来精确识别哪些行同时满足这两个条件。

这两种策略都不是最优的,但仍然比全表扫描好得多,因此它确实建议您应该 - 至少 - 将每个可独立搜索的列作为索引中最左边的列...... ,可以单独查询的任何列,WHERE子句中没有其他列,并返回一个合理大小的结果集。如果结果集的大小不合理,您可能希望限制用户在应用程序中搜索其他属性。

WHERE category = 'x' AND price < 100 AND price > 20更好的索引的情况下是 (category,price) 而不是 (price,category) 但这不是因为WHERE子句中表达式的顺序。这是因为类别是一个平等测试,而价格是一个范围。 WHERE price < 100 AND price > 20 AND category ='x'是等价的,并且 (category,price) 仍然是适当的索引——因为索引按第一列排序,然后在第一列的每个值内,它们按第二列的值排序,然后在每个 (first ,second) pair 它们按第三列中的值排序,无穷大...因此使用 (category,price) 服务器直接转到 category = 'x' 的所有行,并且在索引中的该分组中,引用的行已经按价格排序,因此它只需要选择范围指数类别“x”内的价格。最佳。(price,category) 索引需要检查范围内的所有价格,然后检查所有这些的类别值。索引仍然可以使用,但是根据条件,优化器仍然可以选择扫描整个表。

如果您向WHERE未索引的子句添加第三​​个条件,则将遵循相同的路径,但服务器将扫描已识别的行以查找与非索引列的所需值匹配的行。同样,次优,但通常可以接受,具体取决于您的业务需求——这在确定该问题的正确答案方面发挥了作用。

每个索引都需要空间和资源,因为每次插入、更新和删除都要求服务器立即对受表更改影响的每个索引进行必要的更改。

另请注意,如果您在 (a,b) 或 (a,b,c) 等上有一个索引,那么 (a) 上的单独索引通常被认为是浪费空间,因为 (a,. ..anything-else...) 也将作为 (a) 的索引。

试验 (从 MySQL 5.6 开始EXPLAIN SELECT也支持INSERT// )并真正理解它的输出是理解索引如何工作的不可或缺的工具。MySQL 5.6 还支持,它为您提供优化器如何理解您的查询的详细输出,它考虑的各种计划,它估计每个计划的成本,以及它是如何决定如何执行特定查询的。UPDATEDELETEoptimizer tracing

于 2013-10-28T03:46:04.643 回答