【问题标题】:Need to index column in AND statement?需要在 AND 语句中索引列吗?
【发布时间】:2011-02-17 21:29:54
【问题描述】:

我必须对这样的表执行 SELECT:

  • 身份证
  • 用户名
  • 速度
  • is_running

语句是这样的:

SELECT * 
  FROM mytable 
 WHERE username = 'foo' 
   AND is_running = 1

我有一个关于“用户名”的索引。如果我正在运行上述语句,是否还需要索引“is_running”以获得最佳性能?还是只有选择的第一列有所不同?我正在使用 mysql 5.0。

【问题讨论】:

  • 假设 is_running 是布尔值,索引不会产生影响,因为没有足够的可能性。
  • 什么是用户名索引选择性? (即总共有多少行,有多少个唯一用户名)

标签: sql mysql indexing query-optimization


【解决方案1】:

这取决于您存储的数据类型。如果它是布尔值,您可能看不到仅从该列上的索引获得的收益。您可能想尝试在两列上添加复合索引:

ALTER TABLE mytable ADD INDEX `IDX_USERNAME_IS_RUNNING` ( `username` , `is_running` );

【讨论】:

  • +1:与其说是数据类型,不如说是数据本身。低基数列不是索引的候选者——即使是 1 或 0 的行的 50/50 拆分也是没有用的。
【解决方案2】:

最终取决于表中的数据量是否需要索引。在许多情况下,如果引擎认为这样更快,它可能只是进行表扫描并一起省略您的索引。你有 100 个用户,还是 100,000 个用户?

在位/布尔列上,您不会为索引使用大量存储空间,因此除非您的插入率非常高,否则它可能不会受到伤害。

【讨论】:

  • 如果 MySQL 期望获得超过 30% 的命中率,它会忽略索引,因此它可能会被忽略,除非分布非常偏斜。
  • @dnagirl - 我见过 MySQL 优化器决定使用索引的实例,即使扫描速度会更快。您可以通过指定要使用的索引或忽略它们来强制执行此行为...
【解决方案3】:

如果您有一个包含 100 万用户的表,并且任何时候只有 1 或 2 个用户在运行 - 当然,按 is_running 索引它会给您带来出色的性能。这个特定的用例最好在列上有 2 个索引单独 - 用户名,正在运行。使用 2 个索引的原因是如果您要求 is_running=0,在这种情况下,它会使用 username 索引。

否则,(用户名,正在运行)上的复合索引有 0% 的机会帮助任何事情。坚持用户名的单一索引。

最后,你真的需要整张唱片吗?选择 *?在接近tipping point 的某些场景中(当 MySQL 认为索引+查找变得比直接扫描效率低时),您可以使此查询比原始查询运行得更快。在(用户名,id)上有一个索引

SELECT mytable.*
FROM (
SELECT id 
  FROM mytable 
 WHERE username = 'foo' 
   AND is_running = 1
) X
INNER JOIN mytable on mytable.id = X.id

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-18
    • 2011-09-22
    • 1970-01-01
    • 2011-06-24
    • 2021-06-22
    相关资源
    最近更新 更多