【问题标题】:Proper indexing for an InnoDB tableInnoDB 表的正确索引
【发布时间】:2016-07-07 07:15:42
【问题描述】:

我有一个包含以下列的 InnoDB 表

  • 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)

我应该如何设置索引

  1. 最大选择速度
  2. 不错的 SELECT 速度和高 INSERT 速度

【问题讨论】:

  • 您多久插入一次记录?
  • 非常频繁,有时高达 1000 倍,通常像每秒 50 次
  • 您选择的字段都是整数。所以可能值得一个覆盖指数。可能值得避免 varchar / char 字段上的索引。请注意,您的主键的最大值为 16777215,每秒插入 50 条记录将在大约 93 小时内溢出。

标签: mysql indexing sql-optimization


【解决方案1】:

对于选择:

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 中)可以“跨越”通过e 的索引。也就是说,在所有 '=' 列之后,在一个 'range' 之前,你有一个 'IN'。

这是一个“覆盖”索引:

INDEX(a, e, d, c)

可能会更好。在体积和“覆盖”之间存在权衡。是否会更好,不容易预测;此外,它可能对某些价值观更好,而对另一些价值观则更糟。这将是 320 字节而不是 20 字节。

(注意:此索引中的列以及其他列必须按给定的顺序排列。)

more.

对于INSERT

LOAD DATA 可能是最好的。但是如果LOAD中的行数过多,可能会对SELECTs产生不利影响。每批 100-1000 行的批处理 INSERTs 也非常好。

VARBINARY

那可能是打包的 MD5 或 IPv6?也可能是BINARY(16)?它并没有像某些人所说的那样对索引造成太大的伤害。

InnoDB

当然,使用 InnoDB,而不是 MyISAM。

【讨论】:

  • 感谢您的解释,是的,VARBINARY 是 IPv6
【解决方案2】:

通过复合或覆盖索引实现最大选择速度。问题是,你的 varchars 会妨碍你。它们(目前至少有一个)太宽而无法覆盖,但你的整数不是。因此,请考虑以最常用的方式选择复合索引,例如

key (i1,i2,i2) 

对于一些整数。

要获得最大的插入速度,请选择LOAD DATA INFILE,这是最快的方法,即使是交互式 GUI 应用程序也是如此。需要对工作表进行一些配置才能引入数据。您将需要处理一些概念,例如数据以前是否存在。并且经常制作特殊的update with a join 模式解决方案,用于将数据从工作表中获取到真实表中。事实是,没有带绑定的循环可以达到这个吞吐量。

【讨论】:

    猜你喜欢
    • 2013-11-26
    • 2020-04-21
    • 1970-01-01
    • 2017-12-03
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 1970-01-01
    • 2022-01-06
    相关资源
    最近更新 更多