4

我有几个表,我想知道我的复合索引是否有用。我正在使用MySQL 5+,但我想这将适用于任何数据库(或不适用?)。

无论如何,说我下表:

username           active
-----------------------------------
Moe.Howard              1
Larry.Fine              0
Shemp.Howard            1

所以我通常选择像:

select * from users where username = 'shemp.howard' and active = 1;

我们的active=1许多表格中都使用了。通常,我的索引将在username列上,但我正在考虑添加活动标志(到同一个索引)。

我的逻辑是,当查询引擎扫描索引时,它会扫描索引,例如:

moe.howard,1
shemp.howard,1
larry.fine,0

Shemp在它击中非活动用户(Larry)之前找到它。

现在,我们的active列通常是TINYINTSUnsigned。但我担心索引可能会落后!

larry.fine,0
moe.howard,1
shemp.howard,1

我应该如何最好地处理这个问题并确保我的索引是正确的?我不应该将活动列添加到与用户名相同的索引吗?或者我应该为活动创建一个单独的索引并使其降序?

谢谢。

4

3 回答 3

2

如果将复合索引中的这两个字段与active标志结合起来作为键的第二部分,那么索引顺序将仅在(iff)两行或多行的名称字段相同时(这在这种情况基于一个假设,即希望系统中的用户名是唯一的)。复合索引中的第一个键将定义键的顺序,只要它们不同。换句话说,如果用户名是唯一的,那么将活动标志添加为复合索引的第二段不会改变索引的顺序。

另外,请注意,对于示例查询,数据库不会“扫描”索引来查找值。相反,它将寻找第一个匹配条目,在给出的示例中,该条目由单个匹配项组成。如果多个条目通过 WHERE 子句,则会发生“扫描”。

话虽如此,除非在很多情况下您有重复的名称,否则我最初的反应是不创建复合键。如果名称“通常”是唯一的,那么您不会使用复合键节省大量成本。另一方面,如果通常有很多具有不同active标志值的重复名称,它可能会有所帮助。那时,您可能只需要进行测试。

于 2013-03-12T13:59:12.840 回答
2

实际上,我们只能猜测查询优化器会尝试和做什么,但是通常建议如果索引的选择性超过 20%,那么全表扫描比索引访问更可取。这意味着即使您索引活跃,索引也很可能实际上不会被使用,因为您的活跃用户比非活跃用户多得多。

MySQL 只能按顺序使用索引,所以如果你创建一个复合索引username,active是完全没有意义的,因为你不会有多个用户具有相同的用户名。

您确实需要分析您的查询需求,然后您可以设计一个索引计划来适应它们。分析每个查询,不要尝试过度优化所有内容,因为这可能会产生负面结果。

于 2013-03-12T13:59:34.993 回答
1

只有当您希望它帮助您过滤入/出的值在统计上具有代表性时,才应添加索引。

这意味着什么?

如果说,WHERE 子句中的过滤器,在您要索引的列上,正在帮助您检索 20% 的行,您应该在其中添加一个索引。这个百分比数字取决于您的特殊情况,应该尝试一下,但这就是想法。

在您的情况下,仅凭名称,您将获得 100% 的排除。在活动列上添加索引将无用,因为它无助于减少最终记录集(除非您可能有 n 次相同的名称但只有一个活动?)

如果您决定只过滤活跃用户,而不关心名称,情况会有所不同。

于 2013-03-12T14:01:46.643 回答