【发布时间】:2022-01-20 23:11:40
【问题描述】:
在我的公司,我们有一张太大的桌子。它只有 4 个字段,索引在下面共享。请注意,我们的数据是按地区分隔的,因此我们在 2 个单独的数据库中具有相同的架构(一个用于 NA,一个用于 EU)。以下数据适用于欧盟,但北美的数据通常是欧盟的 10 倍。
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| other_table_id | int(11) | NO | MUL | NULL | |
| time_index | int(11) | NO | NULL | ||
| value | decimal(18,6) | YES | NULL |
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| my_table | 0 | PRIMARY | 1 | id | A | 833155696 | NULL | NULL | BTREE | |||
| my_table | 0 | index_other_table_and_time_index | 1 | other_table_id | A | 29755560 | NULL | NULL | BTREE | |||
| my_table | 0 | index_other_table_and_time_index | 2 | time_index | A | 833155696 | NULL | NULL | BTREE |
请注意,other_table_id 是另一个表的 id,但它不是在 db 级别强制执行的。 (在 Rails 应用程序级别强制执行)。另请注意,非主索引对其具有唯一性约束。
我们对这张表只有 2 个查询。我们的插入是以下形式的批量插入:
INSERT INTO my_table (value, time_index, other_table_id)
VALUES (1,2,3),(4,5,6)...<5000-10000 tuples later>... (7,8,9)
ON DUPLICATE KEY UPDATE
my_table.value=VALUES(value),
my_table.time_index=VALUES(time_index),
my_table.other_table_id=VALUES(other_table_id);
我们的查询如下:
select other_table_id, time_index, value from my_table where
(other_table_id in (<3000 values>) and time_index between 5800 and 6050 )
or (other_table_id in (<300 values>) and time_index between 800 and 830)
order by other_table_id, time_index;
此表自 2006 年以来不断增长。我们经常看到查询和插入时间 > 60 秒。 (可以在mysql慢查询日志中看到)。我们正在使用 AWS 在 RDS 中提供的最大实例,并且我们已经调整了 IO/内存。
因此,我正在尝试考虑其他方法来提高性能。
我想知道我是否会从删除 id 字段中获得显着的好处?在这种情况下,插入期间所需的值将少一个。我还考虑过基于时间索引的分区,因为大多数查询都使用最近的时间索引。但是我读过分区会使数据库脱机,我会害怕对这么大的数据库进行分区。目前还不清楚数据库会关闭多长时间。
删除 id 字段会给我带来什么重大好处吗?分区会给我带来很大的好处吗?如果是这样,有没有办法在不停机的情况下进行分区?注意我必须在分区之前删除 id 字段,因为 mysql 要求所有索引键都在分区中。我正在考虑在 time_index 上进行分区。
还有哪些其他选择?我们没有只读副本,因此另一种选择是将读取查询移动到只读副本。但是,我不清楚这是否会获得重大胜利,因为我们的问题是更大的表大小而不是加载。请注意,欧盟有约 8.33 亿行,而 NA 有约 3.9B 行。
编辑:澄清价值是一种科学测量。我不确定公司是否允许我对其进行编辑。我还在下面的读取查询中添加了解释查询:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | my_table | range | index_other_table_and_time_index | index_other_table_and_time_index | 8 | NULL | 3432 | Using index condition |
还在联合建议上添加解释查询:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|---|---|---|---|---|---|---|---|---|---|
| 1 | PRIMARY | my_table | range | index_other_table_and_time_index | index_other_table_and_time_index | 8 | NULL | 3118 | Using index condition |
| 2 | UNION | my_table | range | index_other_table_and_time_index | index_other_table_and_time_index | 8 | NULL | 314 | Using index condition |
| NULL | UNION RESULT | <union1,2> | ALL | NULL | NULL | NULL | NULL | NULL | Using temporary; Using filesort |
按照要求解释为json:
{
"query_block": {
"select_id": 1,
"ordering_operation": {
"using_filesort": false,
"table": {
"table_name": "my_table",
"access_type": "range",
"possible_keys": [
"index_other_table_and_time_index"
],
"key": "index_other_table_and_time_index",
"used_key_parts": [
"other_table_id",
"time_index"
],
"key_length": "8",
"rows": 3432,
"filtered": 100,
"index_condition": "(((`mydb`.`my_table`.`other_table_id` in (...list of values)) and (`mydb`.`my_table`.`time_index` between 5800 and 6050)) or ((`mydb`.`my_table`.`other_table_id` in (...list of values...)) and (`mydb`.`my_table`.`time_index` between 800 and 830)))"
}
}
}
}
【问题讨论】:
标签: mysql performance amazon-rds