【发布时间】:2017-02-03 15:34:51
【问题描述】:
抱歉,帖子太长了!
我有一个包含约 30 个表的数据库(InnoDB 引擎)。这些表中只有两个,即“transaction”和“shift”相当大(第一个有 150 万行,而 shift 有 23k 行)。现在一切正常,我对当前数据库大小没有问题。
但是,我们将有一个类似的数据库(相同的数据类型、设计......)但更大,例如,“事务”表将有大约 10 亿条记录(大约 230 万条记录)每天交易),我们正在考虑如何在 MySQL 中处理如此大量的数据? (它是读写密集型的)。我阅读了很多相关的帖子,看看 Mysql(更具体地说是 InnoDB 引擎)是否可以很好地处理数十亿条记录,但我仍然有一些问题。我读过的一些相关帖子如下:
- Can MySQL reasonably perform queries on billions of rows?
- Is InnoDB (MySQL 5.5.8) the right choice for multi-billion rows?
- Best data store for billions of rows
- How big can a MySQL database get before performance starts to degrade
- Why MySQL could be slow with large tables?
- Can Mysql handle tables which will hold about 300 million records?
到目前为止我所了解的如何提高超大表的性能:
- (对于我的情况下的 innoDB 表)增加
innodb_buffer_pool_size(例如,高达 80% 的 RAM)。 另外,我发现了一些其他 MySQL 性能调整设置here in percona blog - 在表上有适当的索引(在查询中使用 EXPLAN)
- 对表进行分区
- MySQL 分片或集群
这是我的问题/困惑:
关于分区,我有点怀疑是否应该使用它。一方面,许多人建议在表很大时提高性能。另一方面,我读过很多帖子说它不会提高查询性能并且不会使查询运行得更快(例如,here 和 here)。另外,我在MySQL Reference Manual 中读到 InnoDB 外键和 MySQL 分区不兼容(我们有外键)。
关于索引,目前它们表现良好,但据我了解,对于非常大的表,索引更具限制性(正如 Kevin Bedell 在他的回答 here 中提到的那样)。此外,索引加快了读取速度,同时减慢了写入速度(插入/更新)。那么,对于我们将拥有这个大型数据库的新类似项目,我们是否应该首先插入/加载所有数据,然后创建索引? (加快插入速度)
如果我们不能对我们的大表(“事务”表)使用分区,有什么替代选项可以提高性能? (MySQl 变量设置如
innodb_buffer_pool_size除外)。我们应该使用 Mysql 集群吗? (我们也有很多连接)
编辑
这是我们最大的名为“transaction”的表的show create table 语句:
CREATE TABLE `transaction` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`terminal_transaction_id` int(11) NOT NULL,
`fuel_terminal_id` int(11) NOT NULL,
`fuel_terminal_serial` int(11) NOT NULL,
`xboard_id` int(11) NOT NULL,
`gas_station_id` int(11) NOT NULL,
`operator_id` text NOT NULL,
`shift_id` int(11) NOT NULL,
`xboard_total_counter` int(11) NOT NULL,
`fuel_type` int(11) NOT NULL,
`start_fuel_time` int(11) NOT NULL,
`end_fuel_time` int(11) DEFAULT NULL,
`preset_amount` int(11) NOT NULL,
`actual_amount` int(11) DEFAULT NULL,
`fuel_cost` int(11) DEFAULT NULL,
`payment_cost` int(11) DEFAULT NULL,
`purchase_type` int(11) NOT NULL,
`payment_ref_id` text,
`unit_fuel_price` int(11) NOT NULL,
`fuel_status_id` int(11) DEFAULT NULL,
`fuel_mode_id` int(11) NOT NULL,
`payment_result` int(11) NOT NULL,
`card_pan` text,
`state` int(11) DEFAULT NULL,
`totalizer` int(11) NOT NULL DEFAULT '0',
`shift_start_time` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `terminal_transaction_id` (`terminal_transaction_id`,`fuel_terminal_id`,`start_fuel_time`) USING BTREE,
KEY `start_fuel_time_idx` (`start_fuel_time`),
KEY `fuel_terminal_idx` (`fuel_terminal_id`),
KEY `xboard_idx` (`xboard_id`),
KEY `gas_station_id` (`gas_station_id`) USING BTREE,
KEY `purchase_type` (`purchase_type`) USING BTREE,
KEY `shift_start_time` (`shift_start_time`) USING BTREE,
KEY `fuel_type` (`fuel_type`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1665335 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT
感谢您的宝贵时间,
【问题讨论】:
-
呵呵——“长帖”产生“长答案”。
标签: mysql database performance indexing partitioning