【发布时间】:2019-01-30 09:50:50
【问题描述】:
我们有一个包含以下列的大型 MySQL 表 (device_data):
ID (int)
dt (timestamp)
serial_number (char(20))
data1 (double)
data2 (double)
... // other columns
该表每天接收大约 1000 万行。
我们根据时间戳的日期 (device_data_YYYYMMDD) 对表进行了分片。但是,我们认为这并不有效,因为我们的大多数查询(如下所示)总是检查“serial_number”并且会跨多个日期执行。
SELECT * FROM device_data WHERE serial_number = 'XXX' AND dt >= '2018-01-01' AND dt <= '2018-01-07';
因此,我们认为根据序列号创建分片会更有效。基本上,我们将拥有:
device_data_<serial_number>
device_data_0012393746
device_data_7891238456
因此,当我们要查找特定设备的数据时,我们可以很容易地引用为:
SELECT * FROM device_data_<serial_number> WHERE dt >= '2018-01-01' AND dt <= '2018-01-07';
这种方法似乎很有效,因为:
- 应用程序始终会首先访问基于设备的数据。
- 我们检查了没有先指定设备序列号的查询访问数据。
- 每个设备的表格都相对较小(每天 9000 行)
我们认为我们将面临的一些挑战是:
- 我们有很多设备。这意味着表 device_data_ 也会很多。我已经检查过 MySQL 没有限制数据库中的表数量。与将它们放在一个表中相比,这会影响性能吗?
- 这将如何影响我们以后想要扩展 MySQL(例如使用主/从等)?
- 是否有其他替代方案/解决方案可以解决此问题?
更新。下面是我们现有表的 show create table 结果:
CREATE TABLE `test_udp_new` (
`id` int(20) unsigned NOT NULL AUTO_INCREMENT,
`dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`device_sn` varchar(20) NOT NULL,
`gps_date` datetime NOT NULL,
`lat` decimal(10,5) DEFAULT NULL,
`lng` decimal(10,5) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `device_sn_2` (`dt`,`device_sn`),
KEY `dt` (`dt`),
KEY `data` (`data`) USING BTREE,
KEY `test_udp_new_device_sn_dt_index` (`device_sn`,`dt`),
KEY `test_udp_new_device_sn_data_dt_index` (`device_sn`,`data`,`dt`)
) ENGINE=InnoDB AUTO_INCREMENT=44449751 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
最常运行的查询:
SELECT *
FROM test_udp_new
WHERE device_sn = 'xxx'
AND dt >= 'xxx'
AND dt <= 'xxx'
ORDER BY dt DESC;
【问题讨论】:
-
你考虑过串行分区吗?手动:dev.mysql.com/doc/refman/5.7/en/partitioning.html
-
@fifonik - “串行”??那是什么? This 显示类型,但唯一有用的是
BY RANGE。 -
让我们检查更多的东西 -- 多少 RAM?现在表中有多少 GB?当你停止收集数据时有多少?
innodb_buffer_pool_size的值是多少? -
我的意思是
PARTITION BY HASH(func())。在最简单的情况下, func 可能是 crc32(left(serial_number, 10)) 或更有用的东西,因为我不知道您的序列号格式,所以我无法建议。无论如何,我不会进行分片,因为以后支持数百万个表可能会很痛苦(想象你想在那里添加/更改列或在一个查询中获取多个序列的数据)。 -
@RickJames 现在我们在 16GB 中设置了大约 12GB 的 RAM。当表达到大约 100M 行并且表大小达到大约 10GB(即 innodb_buffer_pool_size 开始用完)时,这很容易变满。
标签: mysql database database-design