带插入的大型表上的mysql性能问题

时间:2015-03-09 19:29:27

标签: php mysql

我们有一个专用服务器,内存为8GB,PHP5.3为MySQL 5.1

最多有大约500个并发连接,每个连接使用用户数据对较小的表执行1-2次SELECT查询,然后在大表transactions中执行INSERT。选择查询不会花费太多时间,我们在每个查询之间添加了监视功能,以查看每个查询的响应时间,并且从来没有问题。

我们在代码中添加了跟踪功能,有时会导致一些简单的INSERT查询需要14-15秒。下面列出的此查询有时需要14秒,有时为6秒,有时为0.2秒或更短。可能是什么问题?

PHP代码有时会返回这些巨大的延迟:

$starT = microtime(true);
echo '&timestampTS_02='.(microtime(true) - $startT);
mysqli_query($GLOBALS['con'],"INSERT INTO `transactions` (`id`,`data`) VALUES('id','some_data')") or die(mysqli_error($GLOBALS['con']));
echo '&timestampTS_03='.(microtime(true) - $startT);

到目前为止,transactions表有大约200万个条目。

CREATE TABLE IF NOT EXISTS `transactions` (
  `id` int(11) NOT NULL,
  `data` varchar(1000) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;

6 个答案:

答案 0 :(得分:5)

InnoDB的。 (因为下面的一些事情需要它。)

批量插入。 Either by INSERT ... VALUES (1,2,3), (4,5,6), ...LOAD DATA。 (一次插入100行时性能提升10倍。)如果您不能“批量”,请参阅下面的“临时表”建议。

innodb_flush_log_at_trx_commit = 2(不是默认值1)(这可能是您的测试无法表现出良好性能的原因。)

innodb_buffer_pool_size =可用内存的70%。 (8GB机器中约5000M)。

从5.1升级。 (但这不能单独解决问题。)

如果可能,请减少transactions上的索引数。

对于非常高的摄取率,请按High Speed Ingestion中讨论的方式打乒乓两个“临时表”。

答案 1 :(得分:4)

您的桌子可能会被锁定以进行其他处理。这可能是硬件问题(缓慢或终身硬盘驱动器),软件或猜测(共享系统中的服务器速度慢)。

您可以通过show processlist

观看锁定插件的内容

答案 2 :(得分:3)

在任何数据库(无论引擎)the highest cost is always in writing data中,因为您添加了强制磁盘操作的开销(具有足够的RAM,MySQL服务器可以很好地缓存表和查询以避免{{{I}的高I / O 1}})。 MyISAM(带表锁定)可能无法帮助对比InnoDB(带行锁定),但您不一定要切换存储引擎。

多个插入的一个主要提示是使用prepared statement。您将查询设置一次,然后更改参数并每行执行一次。正如MySQL Manual for speed(强调我的)

中所述
  

插入行所需的时间由以下因素决定,其中数字表示大致比例:
  连接:(3)
  向服务器发送查询:(2)
  解析查询:(2)
  插入行:(1×行的大小)
  插入索引:(1×索引数)
  结束:(1)

由于预处理语句只发送和解析一次(上面用粗体表示),因此可以节省相当多的开销,并保护数据插入。

另一种选择是启用concurrent inserts。如果您不从该表中删除数据,这只是一个选项。

最后一个对您来说可能并不可行,但如果这是您业务的主要痛点,应该考虑一下。现代云计算大大降低了更高I / O选项(RAID,SSD等)的成本。您可能希望切换到具有高I / O选项的云服务(AWS,Azure等)。您可以在数据库中丢弃任意数量的RAM,但如果存储速度很慢,则只会拖动数据库的其余部分。

答案 3 :(得分:1)

首先检查transactions表是否被引用为外键的持有者。

然后运行show triggers并检查是否有任何触发器设置为在transactions或任何引用表中发生更改时运行。

然后调整找到的任何触发器。

如果这没有帮助,请返回到您添加到代码中的跟踪,并添加以下内容:在运行查询之前,检查当时已运行的查询并记录该查询。可能你会发现一些已经运行的慢查询锁定你的表。

答案 4 :(得分:0)

您应该使用InnoDB引擎代替MyISAM 您可以通过此站点配置您的mysql配置:
www.percona.com

注意:innodb-buffer-pool在您的配置中非常重要

答案 5 :(得分:0)

对大数据使用mysqli,它有多个插入语句功能。

在专用服务器中更可取。

请参阅链接 - http://www.w3schools.com/php/php_mysql_insert_multiple.asp

此致