【问题标题】:MySQL: What are the drawbacks of indexing an additional field?MySQL:索引附加字段的缺点是什么?
【发布时间】:2011-04-13 00:11:28
【问题描述】:

我就是这样的:

CREATE TABLE  UserTrans (
 `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
   `transaction_id` varchar(255) NOT NULL default '0',
  `source` varchar(100) NOT NULL,
   PRIMARY KEY (`id`),
   KEY `user_id` (`user_id`)
)

使用 innodb 引擎。

transaction_id 是 var,因为有时它可能是字母数字。

id 是主键。

所以.. 事情是这样的,我有超过 100 万条记录。但是,有一个查询可以检查指定源上是否存在重复的 transaciton_id。所以,这是我的查询:

SELECT * 
  FROM UserTrans 
 WHERE transaction_id = '212398043' 
   AND source = 'COMPANY_A';

这个查询变得非常慢,现在要运行 2 秒。我应该索引 transaction_id 和源吗?
例如键join_id (transaction_id, source)

如果我这样做有什么缺点?

【问题讨论】:

    标签: php mysql indexing


    【解决方案1】:

    主要缺点是新索引会占用磁盘空间。它还会使插入和更新稍微慢一些(但在大多数情况下这通常可以忽略不计)。

    另一方面,您的查询可能会在几毫秒而不是 2 秒内运行。

    【讨论】:

      【解决方案2】:

      添加索引的缺点是空间(因为存储索引确实占用空间)和插入时间(因为当您插入新记录时,它们必须添加到索引中)。

      也就是说,您可能不需要索引两个字段 - 只需索引其中一个就足够了。

      【讨论】:

        【解决方案3】:

        显然,这样做的好处是可以提高某些查询的性能。

        缺点是存储索引需要一点空间,RDBMS维护索引需要一些工作。索引特别容易占用空间,因为您的 transaction_id 是一个很宽的字符串。

        您可能会考虑 transaction_id 是否真的需要长达 255 个字符,或者您是否可以将其最大长度声明为更短。

        或者您可以使用 前缀索引 仅索引前 n 个字符:

        CREATE INDEX join_id ON UserTrans (transaction_id(16), source(16));
        

        @Daniel 有一个很好的观点,即您可以通过仅索引一列获得相同的好处并节省更多空间。由于您正在使用SELECT *,因此您已经排除了覆盖索引的好处。

        另外,如果您希望 transaction_id 是唯一的,为什么不将其限制为唯一呢?

        CREATE UNIQE INDEX uq_transaction_id ON UserTrans (transaction_id(16));
        

        【讨论】:

        • @Bill... 我认为 OP 也可以考虑仅在 transaction_id 上使用索引(或前缀索引),以节省空间...特别是如果 transaction_id 几乎是唯一的.你怎么看?
        • Transaction Id 不是唯一的。当它与源头在一起时,它是独一无二的。 :) 另外,我实际上不执行 SELECT *,而是只返回记录 ID。 :)
        • @seatoskyhk:如果您只是返回id,您还可以将id 字段添加到索引的右侧,以获得更快的速度。在这种情况下,数据库将拥有索引中的所有信息来为查询提供服务,而不必使用实际的表。这称为覆盖指数。因此,您可能想尝试:(transaction_id(16), source(16), id)... 这显然是速度权衡的另一个空间。
        • @Daniel Vassallo:我猜如果使用前缀索引,覆盖索引没有任何好处。也就是说,查询无论如何都必须从表中读取数据行,以仔细检查它是否与值匹配。
        • @Bill:是的,你是对的。我忽略了这个事实......它必须是 (transaction_id, source, id) 才能从覆盖索引中受益。
        【解决方案4】:

        我会考虑拆分您的 id 列并使用 transaction_id 作为您的主键 我假设 transaction_id 是唯一的。

        这意味着您的架构会阻止您插入已经存在的事务 ID。

        这减少了存储的数据量,也减少了需要索引的列数。

        如果源公司和 transaction_id 实际上是一个复合键.. 我会将这两列设为主键。

        您当前的架构允许您输入重复项,这是不必要的。

        【讨论】:

        • 不幸的是,每个来源的交易 ID 都是唯一的,但有些来源没有交易 ID。这就是原因。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-21
        • 2011-07-23
        • 2011-02-24
        • 1970-01-01
        • 1970-01-01
        • 2010-10-02
        • 2010-10-20
        相关资源
        最近更新 更多