我有一张包含数百万条记录的大表。
Table `price`
------------
id
product
site
value
该表是全新的,并且没有创建索引。
然后,我使用以下查询发出了创建新索引的请求:
CREATE INDEX ix_price_site_product_value_id ON price (site, product, value, id);
这花了很长时间,上次我检查时跑了5000多秒,因为机器。
我想知道如果我发布另一个索引创建,它会在进程计算中使用现有索引吗?如果是这样的话?
接下来运行查询1:
CREATE INDEX ix_price_product_value_id ON price (product, value, id);
接下来运行查询2:
CREATE INDEX ix_price_value_id ON price (value, id);
答案 0 :(得分:5)
我想知道如果我发布另一个索引创建,它会在进程计算中使用现有索引吗?如果是这样的话?
不,它不会。
理论上,(site, product, value, id)
上的索引具有在这些字段的任何子集上构建索引所需的一切(包括(product, value, id)
和(value, id)
上的索引。)
但是,不支持从辅助索引构建索引。
首先,MySQL
不支持快速完整索引扫描(即以物理顺序而不是逻辑顺序扫描索引),从而使索引访问路径比表读取更昂贵。这不是InnoDB
的问题,因为表本身始终是聚集的。
其次,这些索引中的记录顺序完全不同,因此无论如何都需要对记录进行排序。
但是,MySQL
中索引创建速度的主要问题是它在站点上生成订单(只是将记录逐个插入B-Tree
)而不是使用预先排序的源。正如@Daniel所提到的,快速索引创建解决了这个问题。它作为5.1
的插件提供,并预装在5.5
。
答案 1 :(得分:4)
如果您使用的是MySQL 5.1版和InnoDB存储引擎,则可能需要使用InnoDB Plugin 1.0,它支持名为Fast Index Creation的新功能。这允许存储引擎创建索引而不复制整个表的内容。
InnoDB插件概述:
从版本5.1开始,MySQL AB推出了“可插拔”存储引擎架构的概念,该架构允许将多个存储引擎添加到MySQL。但是,目前大多数用户只访问了由MySQL AB分发的存储引擎,并链接到二进制(可执行)版本。
自2001年以来,MySQL AB已经发布了InnoDB事务存储引擎及其版本(源代码和二进制代码)。从MySQL 5.1版开始,用户可以交换一个版本的InnoDB并使用另一个版本。
快速索引创建概述:
在高达5.0的MySQL版本中,如果表有很多行,在具有现有数据的表上添加或删除索引可能会非常慢。
CREATE INDEX
和DROP INDEX
命令通过创建使用请求的索引集定义的新空表来工作。然后,它将现有行逐个复制到新表,随时更新索引。以这种方式将条目插入到索引中,其中键值未被排序,需要随机访问索引节点,并且远非最佳。复制原始表中的所有行后,将删除旧表,并使用原始表的名称重命名该副本。从版本5.1开始,MySQL允许存储引擎创建或删除索引,而无需复制整个表的内容。但是,MySQL版本5.1中的标准内置InnoDB没有利用此功能。但是,使用InnoDB插件,用户在大多数情况下可以比以前的版本更有效地添加和删除索引。
...
更改聚簇索引需要复制数据,即使使用InnoDB插件也是如此。但是,使用InnoDB插件添加或删除辅助索引要快得多,因为它不涉及复制数据。