Sql 为什么insert查询有时需要这么长时间才能完成?

Sql 为什么insert查询有时需要这么长时间才能完成?,sql,mysql,performance,query-cache,Sql,Mysql,Performance,Query Cache,这是一个相当简单的问题。将数据插入表通常工作正常,但插入查询需要几秒钟的时间除外。(我没有尝试批量插入数据。)因此,我为插入过程设置了一个模拟,以找出为什么插入查询有时需要超过2秒才能运行。Joshua建议可能正在调整索引文件;我删除了id(主键字段),但延迟仍然发生 我有一个MyISAM表:daniel\u test\u insert(此表开始时完全为空): 我将数据插入其中,有时插入查询运行时间超过2秒。此表上没有读取-仅由单线程程序串行写入 我运行了100000次完全相同的查询,以找出查询

这是一个相当简单的问题。将数据插入表通常工作正常,但插入查询需要几秒钟的时间除外。(我没有尝试批量插入数据。)因此,我为插入过程设置了一个模拟,以找出为什么插入查询有时需要超过2秒才能运行。Joshua建议可能正在调整索引文件;我删除了id(主键字段),但延迟仍然发生

我有一个MyISAM表:
daniel\u test\u insert
(此表开始时完全为空):

我将数据插入其中,有时插入查询运行时间超过2秒。此表上没有读取-仅由单线程程序串行写入

我运行了100000次完全相同的查询,以找出查询有时需要很长时间的原因。到目前为止,这似乎是随机发生的

例如,此查询花费了4.194秒(对于插入来说是很长的时间):

(这是SHOW PROFILE命令的缩写版本,我抛出了所有为零的列。)

现在更新有难以置信的上下文切换和小页面错误。此数据库上打开的\u表大约每10秒增加1个(没有用完表\u缓存空间)

统计数据:

  • MySQL 5.0.89

  • 硬件:32千兆ram/8核@2.66GHz;raid 10 SCSI硬盘(SCSI II???)

  • 我已询问过硬盘驱动器和raid控制器:未报告任何错误。 CPU大约有50%空闲

  • iostat-x 5(报告硬盘利用率低于10%) 顶级报告平均负载约为10,持续1分钟(对于我们的db机器来说是正常的)

  • 交换空间已使用156k(32千兆ram)


我不知道是什么导致了这种性能滞后。这不会发生在我们的低负载从机上,只会发生在我们的高负载主机上。内存和innodb表也会出现这种情况。有人有什么建议吗?(这是一个生产系统,所以没有什么特别的!)

我在使用INNODB表时遇到了这个问题。(而且INNODB索引的重写速度甚至比MYISAM还要慢)

我假设您正在其他一些表上执行多个其他查询,因此问题是MySQL必须处理文件中的磁盘写入,这些文件变得越来越大,并且需要为这些文件分配额外的空间

如果您使用MYISAM表,我强烈建议您使用

LOAD DATA INFILE 'file-on-disk' INTO TABLE `tablename` 
指挥部;MYISAM的速度非常快(即使使用主键),文件可以格式化为csv,您可以指定列名(或者可以将NULL作为自动增量字段的值)


.

我给你的第一个提示是禁用自动提交功能,然后手动提交

LOCK TABLES a WRITE;
... DO INSERTS HERE
UNLOCK TABLES;
这有利于性能,因为索引缓冲区在所有INSERT语句完成后只刷新到磁盘一次。通常,索引缓冲区刷新的数量与INSERT语句的数量相同

但这可能是您所能做的最好的事情,如果在应用程序中可以做到这一点,您可以通过一次选择进行批量插入

这是通过向量绑定完成的,这是最快的方式

Instead
of:
"INSERT INTO tableName values()"
DO
"INSERT INTO tableName values(),(),(),().......(n) " ,

但是只有当你使用的MySQL驱动程序可以使用参数向量绑定时,才考虑这个选项。


否则,我将倾向于第一种可能性,并为每1000个插入锁定表。不要为100k插入锁定它,因为这样会导致缓冲区溢出。

请阅读Myisam性能:

搜索:


“MyISAM密钥块大小密钥块大小很重要”(减去单引号),这可能就是发生的情况。我想他们用5.1解决了一些这类问题。你能再创建一个包含400(非空)列的表并再次运行测试吗?如果慢速插入的数量增加,这可能表明MySQL在浪费时间编写记录。(我不知道它是如何工作的,但他可能正在移动更多的块,或者移动一些东西以避免碎片……真的不知道)

你能检查一下磁盘子系统的统计信息吗?I/O是否已饱和?这听起来像是内部数据库正在将数据刷新到磁盘/日志

要检查磁盘是否运行不正常,如果您在Windows中,可以创建一个创建10000个文件的批处理cmd文件:

@echo OFF
FOR /L %%G IN (1, 1, 10000) DO TIME /T > out%%G.txt
将其保存在temp dir中,如test.cmd

使用/E:ON参数启用运行CMD的命令扩展

CMD.exe /E:ON
然后运行批处理,查看第一个输出文件和最后一个输出文件之间的时间是否以秒或分钟为单位


在Unix/Linux上,您可以编写类似的shell脚本

服务器中是否有SSD驱动器?某些SSD驱动器出现“studer”问题,这可能会导致您的症状

在任何情况下,我都会尝试找出延迟是发生在MySQL还是磁盘子系统中


您的服务器是什么操作系统,MySQL数据在什么文件系统上?

我在我的系统上也注意到了同样的现象。通常需要一毫秒的查询将突然需要1-2秒。我所有的例子都是简单的单表INSERT/UPDATE/REPLACE语句,而不是任何SELECT语句。没有明显的负载、锁定或螺纹堆积

我曾怀疑这是由于清除脏页、刷新磁盘更改或某些隐藏的互斥,但我还没有缩小范围

也排除了

  • 服务器负载--与高负载无关
  • 引擎——与InnoDB/MyISAM/Memory一起发生
  • MySQL查询缓存——无论是打开还是关闭都会发生
  • 日志循环--事件中没有相关性
在这一点上,我唯一的其他观察结果来自于我在多台机器上运行同一个db的事实。我有一个重读应用程序,所以我使用的是一个带有复制的环境——大部分负载都在从机上。我注意到,即使主机上的负载最小,这种现象也会发生
@echo OFF
FOR /L %%G IN (1, 1, 10000) DO TIME /T > out%%G.txt
CMD.exe /E:ON