【问题标题】:Overhead of Composite Indexes综合指数的开销
【发布时间】:2015-12-01 20:05:49
【问题描述】:

我有很多表,其中我有外键索引,以及包含这些外键的聚集索引。例如,我有一个如下表:

TABLE: Item
------------------------
id       PRIMARY KEY
owner    FOREIGN KEY
status

... many more columns

MySQL 为主键和外键生成索引,但有时,我想提高查询性能,所以我会创建聚集索引或覆盖索引。这会导致索引与列重叠。

INDEXES ON: Item
------------------------
idx_owner (owner)
idx_owner_status (owner, status)

如果我删除了idx_owner,未来通常使用idx_owner 的查询将只使用idx_owner_status,因为它在索引中将owner 作为第一列。

值得保留idx_owner吗?即使 MySQL 只使用部分索引,使用 idx_owner_status 是否有额外的 I/O 开销?

编辑:我真的只对 InnoDB 关于索引的行为方式感兴趣。

【问题讨论】:

    标签: mysql innodb composite-index


    【解决方案1】:

    简答 删除较短的索引。

    长答案 需要考虑的事项:

    放下它:

    • 每个INDEX 都是一个单独的 BTree,驻留在磁盘上,因此会占用空间。
    • 当您INSERT 新行或UPDATE 修改索引列时,每个INDEX 都会更新(迟早)。这需要一些 CPU 和 I/O 以及 buffer_pool 空间用于“更改缓冲区”。
    • 任何功能对较短索引的使用(而不是性能)都可以由较长索引执行。

    别丢了:

    • 较长的索引比较短的索引更庞大。所以它的可缓存性较低。因此(在极端情况下)使用较大的代替较短的可能会导致更多的 I/O。一个加剧这种情况的案例:INDEX(int, varchar255)

    最后一项真正覆盖其他项的情况很少见。

    奖金

    “覆盖”索引是包含所有SELECT 中提到的列的索引。例如:

    SELECT status FROM tbl WHERE owner = 123;
    

    这将触及INDEX(owner, status) 的 BTree,因此明显快于

    SELECT status, foo FROM tbl WHERE owner = 123;
    

    如果您确实需要更快的查询,请将 both 的索引替换为 INDEX(owner, status, foo)

    辅助键中的PK

    还有一个花絮...在 InnoDB 中,PRIMARY KEY 的列隐式附加到每个辅助键。所以,这三个例子真的是

    INDEX(owner, id)
    INDEX(owner, status, id)
    INDEX(owner, status, foo, id)
    

    更多讨论在我的 composite indexesindex cookbook 博客中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-14
      • 1970-01-01
      • 2019-08-10
      • 2023-03-13
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多