【发布时间】:2017-05-13 11:50:53
【问题描述】:
下表包含1000万行,
CREATE TABLE Sample1 (
c1 bigint(20) NOT NULL AUTO_INCREMENT,
c2 varchar(45) NOT NULL,
c3 tinyint(4) NOT NULL DEFAULT 0,
c4 tinyint(4) NOT NULL DEFAULT 0,
c5 varchar(45) DEFAULT NULL,
time bigint(20) DEFAULT NULL,
PRIMARY KEY (c1),
KEY varchar_time_idx (c2,Time),
KEY varchar_c3_time_idx (c2,c3,Time),
KEY varchar_c4_time_idx (c2,c4,Time),
KEY varchar_c3_c4_time_idx (c2,c3, c4,Time)
) ENGINE=InnoDB AUTO_INCREMENT=10093495 DEFAULT CHARSET=utf8;
选择
创建了四个多列索引以在 where 中选择具有以下条件的行
1) c2 和时间
例如:从 Sample1 中选择 c1、c5,其中 c2 = 'sometext' order by time limit 30;
2) c2 和 c3 以及时间
例如:从 Sample1 中选择 c1、c5,其中 c2 = 'sometext' and c3 = int order by time limit 30;
3) c2 和 c4 以及时间
例如:从 Sample1 中选择 c1、c5,其中 c2 = 'sometext' 和 c4 = int 按时间限制 30 排序;
4) c2 和 c3 和 c4 和时间
例如:从 Sample1 中选择 c1、c5,其中 c2 = 'sometext' and c3 = int and c4 = int order by time limit 30;
为了使上面的选择更快,创建了四个多列索引。
基数明智的 c2、c3 和 c4 非常低。 (例如:在一百万个 c2 中,c3 和 c4 各有 100 个唯一列)。
同样分布不均。 c2 中的每个组的行数都是奇数。 (例如:c2 = 1 包含 100000,c2 = 2 包含 1500000 等等)
列时间(以毫秒为单位的时间戳)主要包含唯一字段。
选择正常发生(一小时10到30次,但应该是高速)
插入
插入非常频繁。
但它是按顺序处理的(一个接一个)。
更新
所有更新基于 C1(主键)。 (频率水平:插入时为 20%)
更新 Sample1 设置 c3 = INT,c4 = INT,时间 = CurrentTimeInMilliSecond 其中 c1 = INT
表格有 5 个索引字段(4 个多列)。由于这个
1) 索引字段的插入和更新变得更昂贵
2)随着表的不断增长(可能达到1亿),索引大小也增长得更快
请在 mysql 中提出解决此用例的好方法。
其他必要的细节
innodb_buffer_pool_size:16106127360(15 GB);
CPU 核心:32;
内存:32GB
【问题讨论】:
-
实际上有 10,093,495 行
-
@RiggsFolly 你遇到过同样的情况吗?
-
请向我们展示所有需要这些索引的查询。我们应该首先讨论您是否可以摆脱或合并某些索引。
-
10M 只是十亿的 1/100。也许表“将增长到 1B”?你有多少内存?
innodb_buffer_pool_size的设置是什么?当INSERTing时,c2的值有多随机?time本质上是当前时间吗? (这些问题会导致您判断INSERTs在您到达 1B 时的表现。) -
如果
c2具有低基数,那么它可能应该被规范化并替换为INT(和UNSIGNED)的某种风格。
标签: mysql database-performance