在200米表上缓慢INSERT查询

时间:2015-07-31 10:16:47

标签: mysql insert

我们的下表中有大约2亿条记录:

CREATE TABLE IF NOT EXISTS `history` (
  `airline` char(2) NOT NULL,
  `org` char(3) NOT NULL,
  `dst` char(3) NOT NULL,
  `departat` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `arriveat` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `validon` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `price` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8
/*!50500 PARTITION BY RANGE  COLUMNS(org)
(PARTITION p0 VALUES LESS THAN ('AHI') ENGINE = MyISAM,
 PARTITION p1 VALUES LESS THAN ('ARO') ENGINE = MyISAM,
 ...
 PARTITION p39 VALUES LESS THAN ('WMA') ENGINE = MyISAM,
 PARTITION p40 VALUES LESS THAN (MAXVALUE) ENGINE = MyISAM) */;

--
-- Indexes for table `history`
--
ALTER TABLE `history`
 ADD KEY `tail` (`org`,`dst`,`departat`);

我们经常批量插入一些VALUES,通常在简单的INSERT查询中最多可达1000条记录,而不需要ON DUPLICATE KEY之类的任何修饰(索引不是唯一的)无论如何)。

有时当我在phpMyAdmin中进入服务器状态时,会看到一堆INSERT语句相互等待,有时会持续300-400秒。在特定时间似乎没有其他任何东西在服务器上。我们获得了32 GB的优异性能。

如何解决此问题?谢谢你的帮助。

3 个答案:

答案 0 :(得分:2)

可能第一步是在profiling上进行几次测试。

通常你会做类似的事情:

SET LOCAL PROFILING=ON;
-- run your INSERT, like:
INSERT INTO yourtable (id) VALUES (1),(2),(3);

SHOW PROFILES;
+----------+------------+------------------------------------------------+
| Query_ID | Duration   | Query                                          |
+----------+------------+------------------------------------------------+
|     1012 | 6.25220000 | INSERT INTO yourtable (id) VALUES (1),(2),(3); |
+----------+------------+------------------------------------------------+

这会告诉您非常基本的信息,例如查询的持续时间(在本例中为6.25秒)。要获取实际细节,您需要提取所述查询的配置文件:

SHOW PROFILE FOR QUERY 1025; 
+------------------------------+----------+
| Status                       | Duration |
+------------------------------+----------+
| starting                     | 0.004356 |
| checking permissions         | 0.000015 |
| Opening tables               | 6.202999 |
| System lock                  | 0.000017 |
| init                         | 0.000342 |
| update                       | 0.023951 |
| Waiting for query cache lock | 0.000008 |
| update                       | 0.000007 |
| end                          | 0.000011 |
| query end                    | 0.019984 |
| closing tables               | 0.000019 |
| freeing items                | 0.000304 |
| logging slow query           | 0.000006 |
| cleaning up                  | 0.000181 |
+------------------------------+----------+

您可能会注意到'打开表格花了很长时间。在此示例中,通过将表(LOCK TABLES)锁定为另一个进程来延迟执行来延迟查询执行。有关州的更多信息,请参见manual

答案 1 :(得分:0)

为时间戳字段设置默认值0并尝试

例如:

departat timestamp NOT NULL DEFAULT 0,
arriveat timestamp NOT NULL DEFAULT 0,

Timestamp将存储一个像整数(传递时间的平均时间戳)的值,它不会保留像datetime这样的记录。

在您的情况下,您已在时间戳字段类型

中将默认设置为日期时间格式

答案 2 :(得分:0)

您可以采取一些措施来优化批量插入。 如果你确定你的数据不包含重复项(在上传完成后不要忘记将它们设置为1),其中一项就是设置这些变量:

SET AUTOCOMMIT = 0; SET FOREIGN_KEY_CHECKS = 0; SET UNIQUE_CHECKS = 0;

此外,您还需要检查是否有其他用户正在访问该表。您也可以尝试使用Innodb,因为它表示比MyISAM更好地处理已包含数据的批量插入。

此外,您可以检查表上的碎片,有时在分段驱动器上分配可用空间时操作系统提供的开销是造成延迟的原因。