使用mysql

时间:2016-09-26 10:23:38

标签: mysql database performance indexing partitioning

很抱歉很长的帖子!

我有一个包含~30个表(InnoDB引擎)的数据库。这些表中只有两个,即“事务”和“移位”非常大(第一个有150万行,移位有23k行)。现在一切正常,我没有当前数据库大小的问题。

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

到目前为止,我已经理解为提高非常大的表的性能:

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

    • 关于分区,我怀疑是否应该使用它。一方面,许多人建议在桌子非常大时提高性能。另一方面,我阅读了很多帖子,说它不会提高查询效果,也不会让查询运行得更快(例如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
    

    感谢您的时间,

4 个答案:

答案 0 :(得分:37)

  • 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性能调整设置 - 是

  • 在表上有适当的索引(在查询中使用EXPLAN) - 好吧,让我们看看它们。在 critical 区域可以犯很多错误。

  • 分区表 - “分区不是灵丹妙药!”我在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

  • 每天2,300万笔交易 - 如果是2.3M 插入(30 /秒),那么就没有太多的性能问题。如果更复杂,则可能需要RAID,SSD,批处理等。

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

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

使用mysql处理非常大的数据

#Example file:
Overseas_trade_index data CSV File:
Steps:

1.Need to create table for overseas_trade_index.

2.Need to create columns related to csv file.
#SQL Query:
( id int not null primary key auto_increment,
series_reference varchar (60),
period varchar (60),
data_value decimal(60,0),
status varchar (60),
units varchar (60),
magnitude int(60),
subject text(60),
group text(60),
series_title_1 varchar (60),
series_title_2 varchar (60),
series_title_3 varchar (60),
series_title_4 varchar (60),
series_title_5 varchar (60),
 );

3.Need to connect mysql database in terminal.
=>show databases;
=>use database;
=>show tables;

#Please enter this command to import the csv data to mysql tables.

#load data infile '/home/desktop/Documents/overseas.csv' into table trade_index fields terminated by ',' lines terminated by '\n' (series_reference,period,data_value,status,units,magnitude,subject,series_title1,series_title_2,series_title_3,series_title_4,series_title_5);#

=>Find this overseas trade index data on sqldatabase:
#Query:
select * from trade_index;

答案 3 :(得分:0)

使用实时 VTS 系统轻松交叉 2.7 BL 数据。特殊情况是数据库不仅存储数据,实时读取可用性也是一个关键部分,否则就达不到实时跟踪的目的。以下事情首先有帮助;

  1. 漂亮的标准化;
  2. 严重的索引;
  3. InnoDB;
  4. 计算列作为缓存;
  5. 查询优化;
  6. 它在 SSD (VPS) 上使用 x4 内核和 x8 GB RAM 存活(到目前为止)
  7. 报告和待办事项汇总表;