InnoDB table 的正确索引
Proper indexing for an InnoDB table
我有一个 InnoDB table 包含以下列
- id MEDIUMINT UNSIGNED AUTO_INCREMENT
- 一个 VARBINARY(16)
- b CHAR(2)
- c VARCHAR(100)
- d MEDIUMINT UNSIGNED
- e TINYINT UNSIGNED,范围 0-49
大部分时间我都会执行这样的查询
SELECT d, e, c FROM tbl WHERE a=0x5caffbb2 AND d>1000000 AND (e=1 OR e=5 OR e=6 OR e=8 OR e=15)
我应该如何为
设置索引
- 最大SELECT速度
- 体面的 SELECT 速度和高 INSERT 速度
通过复合或覆盖索引达到最大select速度。问题是,您的 varchars 会妨碍您。它们(目前至少有一个)太宽而无法覆盖,但您的整数却没有。所以考虑选择最常用的复合索引如
key (i1,i2,i2)
一些整数。
要获得最大插入速度,请选择 LOAD DATA INFILE
,这是最快的方法,即使在交互式 GUI 应用程序中也是如此。引入数据需要一些 worktable 的配置。您将需要兼顾一些概念,例如数据以前是否存在。并且经常设计特殊的 update with a join
模式解决方案,以便将工作 table 中的数据转化为真实的 table。事实是,没有带绑定的循环将实现此吞吐量。
对于select:
INDEX(a, d)
索引中的第一列,即 a
,应与“= 常量”进行比较。
然后是一个范围,即d > ...
。
由于 OR
,其他内容很难编入索引。但是,都是同一个变量:e=1 OR e=5 OR e=6 OR e=8 OR e=15
,相当于e IN (1, 5, 6, 8, 15)
。所以,这样更好:
INDEX(a, e, d)
这是因为优化器(在 5.6 中)可以 "leapfrog" 通过 e
的索引。也就是说,在所有“=”列之后,在 'range' 之前,您有一个 'IN'.
这是一个 "covering" 索引:
INDEX(a, e, d, c)
可能会更好。在体积和 "covering" 之间需要权衡。很难预测它是否会更好;此外,它可能对某些价值观更好,对其他价值观更糟。这将是 320 字节而不是 20。
(注意:此索引中的列,以及其他列,必须按给定的顺序排列。)
more.
为INSERT
LOAD DATA
可能是最好的。但是,如果 LOAD
中的行数过多,可能会对 SELECTs
产生不利影响。每批 100-1000 行的批处理 INSERTs
也非常好。
VARBINARY
这可能是打包的 MD5 或 IPv6?也可能是BINARY(16)
?它并没有像一些人说的那样对索引造成太大的伤害。
InnoDB
当然是用InnoDB,不用MyISAM
我有一个 InnoDB table 包含以下列
- id MEDIUMINT UNSIGNED AUTO_INCREMENT
- 一个 VARBINARY(16)
- b CHAR(2)
- c VARCHAR(100)
- d MEDIUMINT UNSIGNED
- e TINYINT UNSIGNED,范围 0-49
大部分时间我都会执行这样的查询
SELECT d, e, c FROM tbl WHERE a=0x5caffbb2 AND d>1000000 AND (e=1 OR e=5 OR e=6 OR e=8 OR e=15)
我应该如何为
设置索引- 最大SELECT速度
- 体面的 SELECT 速度和高 INSERT 速度
通过复合或覆盖索引达到最大select速度。问题是,您的 varchars 会妨碍您。它们(目前至少有一个)太宽而无法覆盖,但您的整数却没有。所以考虑选择最常用的复合索引如
key (i1,i2,i2)
一些整数。
要获得最大插入速度,请选择 LOAD DATA INFILE
,这是最快的方法,即使在交互式 GUI 应用程序中也是如此。引入数据需要一些 worktable 的配置。您将需要兼顾一些概念,例如数据以前是否存在。并且经常设计特殊的 update with a join
模式解决方案,以便将工作 table 中的数据转化为真实的 table。事实是,没有带绑定的循环将实现此吞吐量。
对于select:
INDEX(a, d)
索引中的第一列,即 a
,应与“= 常量”进行比较。
然后是一个范围,即d > ...
。
由于 OR
,其他内容很难编入索引。但是,都是同一个变量:e=1 OR e=5 OR e=6 OR e=8 OR e=15
,相当于e IN (1, 5, 6, 8, 15)
。所以,这样更好:
INDEX(a, e, d)
这是因为优化器(在 5.6 中)可以 "leapfrog" 通过 e
的索引。也就是说,在所有“=”列之后,在 'range' 之前,您有一个 'IN'.
这是一个 "covering" 索引:
INDEX(a, e, d, c)
可能会更好。在体积和 "covering" 之间需要权衡。很难预测它是否会更好;此外,它可能对某些价值观更好,对其他价值观更糟。这将是 320 字节而不是 20。
(注意:此索引中的列,以及其他列,必须按给定的顺序排列。)
more.
为INSERT
LOAD DATA
可能是最好的。但是,如果 LOAD
中的行数过多,可能会对 SELECTs
产生不利影响。每批 100-1000 行的批处理 INSERTs
也非常好。
VARBINARY
这可能是打包的 MD5 或 IPv6?也可能是BINARY(16)
?它并没有像一些人说的那样对索引造成太大的伤害。
InnoDB
当然是用InnoDB,不用MyISAM