抱歉发了这么长的帖子!

我有一个包含约30个表的数据库(InnoDB引擎).其中只有两个表,即"transaction"和"shift"相当大(第一个表有150万行,而shift表有23k行).现在一切正常,我对当前的数据库大小没有问题.

然而,我们将有一个类似的数据库(相同的数据类型、设计等等)但是要大得多,例如,"transaction"表将有大约1 billion records个(每天大约230万个事务),我们正在考虑如何在MySQL中处理如此大量的数据?(它是读写密集型的).我阅读了很多相关帖子,想看看Mysql(更具体地说是InnoDB引擎)能否在数十亿条记录上表现良好,但我仍然有一些问题.以下是我读过的一些相关帖子:

到目前为止,我对提高超大表性能的理解是:

  1. (对于我的innoDB表)增加innodb_buffer_pool_size(例如,最多80%的RAM).
  2. 在表上有适当的索引(在查询中使用EXPLAN)
  3. 对表进行分区
  4. MySQL分片或集群

以下是我的问题/困惑:

  • 关于分区,我怀疑我们是否应该使用它.一方面,很多人建议在桌子很大的时候提高性能.另一方面,我读过很多帖子,说它不会提高查询性能,也不会让查询运行得更快(例如,herehere).此外,我在MySQL Reference Manual中读到InnoDB foreign keys and MySQL partitioning are not compatible(我们有外键).

  • 关于索引,目前它们的性能很好,但据我所知,对于非常大的表,索引更具限制性(正如Kevin Bedell在他的答案here中提到的).此外,索引加快了读取速度,同时降低了写入速度(插入/更新).那么,对于新的类似项目,我们将有这么大的数据库,我们应该首先插入/加载所有数据,然后创建索引吗?(以加快插入速度)

  • 如果我们不能对我们的大表("事务"表)使用分区,那么有什么替代选项可以提高性能?(MySQl变量设置除外,例如innodb_buffer_pool_size).我们应该使用Mysql集群吗?(我们也有很多加入)

EDIT

这是我们最大的名为"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能合理地对数十亿行执行查询吗?——MySQL可以"处理"数十亿行."合理"取决于询问;让我们看看.

  • InnoDB(MySQL 5.5.8)是数十亿行的正确 Select 吗?——5.7有一些改进,但5.5相当不错,尽管已经快6岁了,而且即将不再受支持.

  • 数十亿行的最佳数据存储——如果你指的是"引擎",那就是InnoDB.

  • 在性能开始下降之前,MySQL数据库能有多大?同样,这取决于查询.我可以给你看一张1K排的桌子,它会融化;我曾与数亿张嗡嗡作响的桌子打过交道.

  • 为什么MySQL在处理大型表时会比较慢?——范围扫描导致I/O,这是缓慢的部分.

  • Mysql能处理大约3亿条记录的表吗?——再一次,是的.限制大约在一万亿行左右.

  • (对于我的InnoDB表)增加InnoDB_buffer_pool_大小(例如,最多80%的RAM).另外,我在Percona博客中找到了其他一些MySQL性能调优设置——是的

  • 在表上有适当的索引(使用EXPLAIN on查询)——好吧,让我们看看它们.在这方面可能会犯很多错误.

  • 对表进行分区——"分区不是万能的!"我在my blog分钟内反复强调这一点

  • MySQL分片——目前这是DIY

  • MySQL集群——目前最好的答案是一些基于Galera的选项(PXC、MariaDB 10、DIY w/Oracle).甲骨文的"组复制"是一个可行的竞争者.

  • 分区不支持FOREIGN KEY或"全局"UNIQUE.

  • UUID,在你所说的规模上,不仅会减慢系统的速度,而且实际上会杀死它.Type 1 UUIDs可能是一个解决办法.

  • 插入和索引构建速度——有太多的变体,无法给出单一答案.让我们看看你的暂定CREATE TABLE,以及你打算如何输入数据.

  • 很多连接——"正常化,但不要过度正常化."特别是,不要规范化日期时间、浮点数或其他"连续"值.

  • 建造summary tables

  • 每天230万笔交易——如果这是230万笔(30秒),那么性能问题就不大了.如果更复杂,则可能需要RAID、SSD、批处理等.

  • 处理如此大的数据量——如果大多数活动都是"最近"的行,那么缓冲池将很好地"缓存"活动,从而避免I/O.如果活动是"随机"的,那么MySQL(或anyone其他)将有I/O问题.

  • 在像您这样的表中,缩小数据类型会有所帮助.我怀疑你是否需要4个字节来指定fuel_type.有多种1字节方法.

Mysql相关问答推荐

无法从容器从APS. NET应用程序连接到MySQL服务器容器

MariaDB字段+1

MySQL binlog事件上的并发事务行为

MySQL 8.0.34-从后端系统管理AWS RDS上的持久连接内存使用

我可以指示MariaDB-Install-db和MariaDB忽略配置中的用户设置吗?

LaravelEloquent ToSql()缺少连接表

无法连接到扩展坞MySQL Unix套接字

Python - 执行原始 SQL 时获取更新查询 (Mysql) 的结果

MySQL函数 - 如何对select查询应用多个条件

如何查询由另一个查询创建的表?

如何从将分钟、天、月和年存储在不同列中的表中查询数据

无法通过迁移在现有表中插入行 - Rails 6

使用 MySQL 在树中查找 Leaf

如何使用 C++ 连接 mySQL 数据库

用序列号mysql更新列

org.hibernate.InstantiationException:没有实体的默认构造函数::principal.Cliente

如何将 MySQL 5.7 更新到新的 MySQL 8.0?

MySQL错误 1005 (HY000): 无法创建表 'foo.#sql-12c_4' (errno: 150)

MySQL更新查询与左连接和分组依据

将 UTF8 表上的 latin1 字符转换为 UTF8