使用mysql处理非常大的数据

使用mysql处理非常大的数据,mysql,database,performance,indexing,partitioning,Mysql,Database,Performance,Indexing,Partitioning,抱歉发了这么长的帖子 我有一个包含30个表的数据库(InnoDB引擎)。其中只有两个表,即“transaction”和“shift”相当大(第一个表有150万行,而shift有23k行)。现在一切正常,我对当前的数据库大小没有问题 然而,我们将有一个类似的数据库(相同的数据类型、设计等等),但要大得多,例如,“事务”表将有大约10亿条记录(每天大约230万个事务),我们正在考虑如何在MySQL中处理如此大的数据量?(它是读写密集型)。我读了很多相关的帖子,想看看Mysql(更具体地说是InnoD

抱歉发了这么长的帖子

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

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

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

  • (对于我的案例中的innoDB表)增加
    innoDB_buffer_pool_size
    (例如,高达RAM的80%)。 此外,我还发现了一些其他MySQL性能调优设置
  • 在表上有适当的索引(在查询上使用EXPLAN)
  • 对表进行分区
  • MySQL分片或集群
  • 以下是我的问题/困惑:

    • 关于分区,我怀疑我们是否应该使用它。一方面,很多人建议在桌子很大的时候提高性能。另一方面,我读过很多帖子,说它不能提高查询性能,也不能使查询运行得更快(例如,和)。此外,我还了解到InnoDB外键和MySQL分区不兼容(我们有外键)

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

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

    编辑 这是我们最大的名为“transaction”的表的
    show create table
    语句:

    谢谢您的时间,

    • 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_大小(例如,高达RAM的80%)。另外,我在percona博客中发现了其他一些MySQL性能调优设置——是的

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

    • 对表进行分区--“分区不是万能的!”我在

    • MySQL分片——目前这是DIY

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

    • 分区不支持
      外键
      或“全局”
      唯一

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

    • 插入和索引构建速度--有太多的变体,无法给出单个答案。让我们看看您的暂定
      创建表
      ,以及您打算如何输入数据

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

    • 建造

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

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

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


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

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

    Hehe--“长帖子”将产生“长答案”。再来一个
      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