【问题标题】:Indexing only one MySQL column value仅索引一个 MySQL 列值
【发布时间】:2010-03-23 05:52:40
【问题描述】:

我有一个带有状态列的 MySQL InnoDB 表。状态可以是“完成”或“处理中”。随着表的增长,最多 0.1% 的状态值将是“处理中”,而其他 99.9% 的值将是“完成”。由于“处理”的高选择性(尽管不是“完成”),这似乎是索引的一个很好的候选者。是否可以为仅索引值“处理”的状态列创建索引?我不希望索引“完成”索引浪费大量空间。

【问题讨论】:

  • 只是想知道将其转换为名为“处理”的位列是否更容易,其中值为“1”或“0”。会使用更少的空间。 (除非您有超过 2 个状态)
  • 好建议。实际上,我确实有超过 2 个状态,但为了简单起见,我对其进行了简化。
  • “但为了简单起见我简化了它”——那没关系,只要你没有因为其他原因简化它:-)

标签: mysql indexing innodb


【解决方案1】:

我不知道执行此操作的任何标准方法,但我们之前通过使用两个表解决了类似的问题,在您的情况下,ProcessingDone,前者有索引,后者没有。

假设行永远不会从 done 切换回 processing,您可以使用以下步骤:

  1. 创建记录时,将其插入到Processing 表中,并将列设置为processing
  2. 完成后,将列设置为done
  3. 定期扫描Processing 表,将done 行移动到Done 表。

最后一个可能很棘手。您可以在事务中执行插入/删除以确保它正确传输,或者您可以使用唯一 ID 来检测它是否已经传输,然后从 Processing 中删除它(我没有 MySQL 事务支持的经验,这就是为什么我'我也给出了那个选项)。

这样,您只需索引 99.9% 的 done 行中的一小部分,这些行尚未转移到 Done 表中。它也适用于 processing 的多个状态,正如您在 cmets 中提到的那样(条目仅在达到 done 状态时才被传输,所有其他状态都保留在 Processing 表中)。

这类似于将历史数据(永远不会再更改的数据)转移到单独的表中以提高效率。它会使一些查询复杂化,因为您必须连接两个表,因此您需要同时访问 done 和非done 行,因此请注意权衡取舍。

【讨论】:

    【解决方案2】:

    更好的解决方案:不要使用字符串来表示状态。而是在代码中使用具有描述性名称 => 整数值的常量。然后将该整数存储在数据库中,MySQL 将比使用字符串快很多。

    我不知道你用的是什么语言,但例如在 PHP 中:

    class Member
    {
       const STATUS_ACTIVE = 1;
       const STATUS_BANNED = 2;
    }
    
    if ($member->getStatus() == Member::STATUS_ACTIVE)
    {
    }
    

    而不是你现在拥有的:

    if ($member->getStatus() == 'active')
    {
    }
    

    【讨论】:

    • 感谢您的回答。字符串实际上是 ENUM,这意味着它们被映射到整数。虽然您的建议是有效的,但它并没有触及我问题的根源:是否有必要,如果需要,我如何仅索引列中的特定值?
    猜你喜欢
    • 1970-01-01
    • 2015-03-21
    • 2011-01-21
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 2016-08-26
    • 2017-12-10
    • 1970-01-01
    相关资源
    最近更新 更多