【问题标题】:Handling very large data with mysql使用 mysql 处理非常大的数据
【发布时间】:2017-02-03 15:34:51
【问题描述】:

抱歉,帖子太长了!

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

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

到目前为止我所了解的如何提高超大表的性能:

  1. (对于我的情况下的 innoDB 表)增加innodb_buffer_pool_size(例如,高达 80% 的 RAM)。 另外,我发现了一些其他 MySQL 性能调整设置here in percona blog
  2. 在表上有适当的索引(在查询中使用 EXPLAN)
  3. 对表进行分区
  4. MySQL 分片或集群

这是我的问题/困惑:

  • 关于分区,我有点怀疑是否应该使用它。一方面,许多人建议在表很大时提高性能。另一方面,我读过很多帖子说它不会提高查询性能并且不会使查询运行得更快(例如,herehere)。另外,我在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


【解决方案1】:
  • MySQL 能否合理地对数十亿行执行查询? -- MySQL 可以“处理”数十亿行。 “合理”取决于查询;让我们看看他们。

  • InnoDB (MySQL 5.5.8) 是数十亿行的正确选择吗? -- 5.7 有一些改进,但 5.5 已经相当不错了,尽管 已经接近 6 8 年了,并且 濒临 不再被支持。

  • 数十亿行的最佳数据存储——如果您的意思是“引擎”,那么 InnoDB。

  • 在性能开始下降之前,MySQL 数据库可以达到多大 - 同样,这取决于查询。我可以给你看一个会崩溃的 1K 行表;我曾使用过数十亿行的表格。

  • 为什么 MySQL 在处理大表时会变慢? -- 范围扫描导致 I/O,这是缓慢的部分。

  • Mysql 可以处理大约 3 亿条记录的表吗? ——再次,是的。限制大约是一万亿行。

  • (对于 InnoDB 表,这是我的情况)增加 innodb_buffer_pool_size(例如,高达 80% 的 RAM)。另外,我在 Percona 博客中发现了一些其他 MySQL 性能调整设置——是的

  • 在表上有适当的索引(在查询中使用 EXPLAIN)——好吧,让我们看看它们。在这个关键领域可能会犯很多错误。

  • 对表进行分区——“分区不是万能的!”我在my blog 中强调这一点

  • MySQL Sharding -- 目前是 DIY

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

  • 分区不支持FOREIGN KEY 或“全局”UNIQUE

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

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

  • 大量的连接——“规范化,但不要过度规范化。”特别是,不要规范化日期时间或浮点数或其他“连续”值。

  • 构建summary tables

  • 每天 230 万次交易 -- 如果是 230 万次插入(30/秒),那么性能问题就不大了。如果更复杂,则可能需要 RAID、SSD、批处理等。

  • 处理如此大量的数据——如果大多数活动都与“最近”行有关,那么 buffer_pool 将很好地“缓存”活动,从而避免 I/O。如果活动是“随机的”,那么 MySQL(或 任何人 else)将有 I/O 问题。

  • 缩小数据类型有助于像您这样的表。我怀疑您是否需要 4 个字节来指定 fuel_type。有多种 1 字节方法。

【讨论】:

  • 还有一项——“MySQL NDB Cluster”与 Galera 不同; NDB有一个利基市场;它可能对你有用;让我们进一步了解您的应用。
  • 感谢 Rick 的详细回答。现在我主要担心的是我不确定我们是否应该进行聚类(我以前从未做过)。我的意思是我们什么时候应该做,什么时候不应该做?在聚类之前我应该​​考虑哪些因素?如果我们必须这样做,我应该从哪里开始?
  • 另外,您说您应该看到查询(用于索引、性能等)。我应该考虑哪些关于查询的信息?您需要有关我们应用程序的哪些信息?我怎样才能向您显示查询? (对不起,如果这是愚蠢的问题!)
  • 数据类型——汇款?记录?数据仓库?科研读物?
  • 大小确实表示分区的必要性。写活动确实表示需要分片。 HA(高可用性)是“集群”的一项指标。每秒插入/更新超过 100 行表示 一些 操作,但通常无需分片/集群/等即可达到 1000/秒。涉及“分组依据”的海量“报告”表示“汇总表”。等等。
【解决方案2】:

通过实时 VTS 系统顺利通过 2.7 BL 数据。特殊情况是数据库不仅存储数据,实时读取可用性也是至关重要的部分,否则无法满足实时跟踪目的。关注事情首先会有所帮助;

  1. 帅归一化;
  2. 严重的索引;
  3. InnoDB;
  4. 计算列作为缓存;
  5. 查询优化;
  6. 它(到目前为止)在 SSD (VPS) 上使用 x4 内核和 x8 GB RAM 仍然存在
  7. 报告和积压汇总表;

【讨论】:

    【解决方案3】:

    在收集数十亿行时,最好(如果可能)在存储之前 整合、处理、汇总数据。如果您认为需要返回原始数据,请将其保存在文件中。

    这样做将消除您的大部分问题和疑虑,并加快处理速度。

    【讨论】:

    • 我同意。它基本上执行相同数量的处理,但随着时间的推移而不是同时分布。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-13
    • 2011-09-26
    • 1970-01-01
    相关资源
    最近更新 更多