MySQL中的性能问题

时间:2010-12-02 19:18:27

标签: mysql performance optimization

我在mysqld中看到了一个我不理解的表现行为。

我有一个表t,主键id和三个数据列col1,... col4。

数据在4个TSV文件'col1.tsv',...'col4.tsv'中。我用来摄取它们的程序是:

CREATE TABLE t (
  id INT NOT NULL,
  col1 INT NOT NULL,
  col2 INT NOT NULL,
  col3 INT NOT NULL,
  col4 CHAR(12) CHARACTER SET latin1 NOT NULL );

LOAD DATA LOCAL INFILE      # POP 1
  'col1.tsv' INTO TABLE t (id, col1);  

ALTER TABLE t ADD PRIMARY KEY (id);

SET GLOBAL hot_keys.key_buffer_size= # something suitable 
CACHE INDEX t IN hot_keys; 
LOAD INDEX INTO CACHE t;

DROP TABLE IF EXISTS tmpt;
CREATE TABLE tmpt ( id INT NOT NULL, val INT NOT NULL );
LOAD DATA LOCAL INFILE 'col2.tsv' INTO TABLE tmpt tt;
INSERT INTO t (id, col2)    # POP 2 
  SELECT tt.id, tt.val FROM tmpt tt
  ON DUPLICATE KEY UPDATE col2=tt.val;

DROP TABLE IF EXISTS tmpt;
CREATE TABLE tmpt ( id INT NOT NULL, val INT NOT NULL );
LOAD DATA LOCAL INFILE 'col3.tsv' INTO TABLE tmpt tt;
INSERT INTO t (id, col3)    # POP 3
  SELECT tt.id, tt.val FROM tmpt tt
  ON DUPLICATE KEY UPDATE col3=tt.val;

DROP TABLE IF EXISTS tmpt;
CREATE TABLE tmpt ( id INT NOT NULL, 
  val CHAR(12) CHARACTER SET latin1 NOT NULL );
LOAD DATA LOCAL INFILE 'col4.tsv' INTO TABLE tmpt tt;
INSERT INTO t (id, col4)    # POP 4
  SELECT tt.id, tt.val FROM tmpt tt
  ON DUPLICATE KEY UPDATE col4=tt.val;

现在这是我不理解的表演。 POP有时候 和3 INSERT INTO ... SELECT ... ON DUPLICATE KEY UPDATE查询使用mysqld运行得非常快 占用100%的核心,在其他时候,mysqld陷入1%CPU读数t.MYD,即表t的MyISAM数据文件,随机偏移。

我很难隔离它在哪种情况下速度很快 它很慢但我找到了一个可重复的案例:

在上面的序列中,POP 2和3非常慢。但是如果我创造了 没有col4然后POP 2和POP 3非常快。为什么呢?

然后,如果之后,我使用ALTER TABLE查询添加col4,然后运行POP 4 也很快。

同样,当INSERT运行缓慢时,mysqld在文件IO中陷入困境 读取表t的MyISAM数据文件中的随机偏移量。我甚至没有 明白为什么要阅读该文件。

MySQL服务器版本5.0.87。 Core 2 Duo iMac上的OS X 10.6.4。


更新

我最终找到了(我认为是)这个问题的答案。一些插入缓慢而一些快速的神秘差异取决于数据。

线索是:当插入缓慢时,mysqld在t.MYD读取之间平均寻求0.5GB。当它很快时,连续读取具有微小的相对偏移。

由于某些'col?.tsv'文件的行与w.r.t大致相同,所以出现了混乱。 id列,而其他列是相对于它们随机排序的。

在加载和插入tsv文件之前,我可以通过在tsv文件上使用sort(1)来大幅缩短整体处理时间。

1 个答案:

答案 0 :(得分:0)

这是一个非常开放的问题......这是一个推测性的,开放的答案。 :)

  

...当INSERT运行缓慢时,mysqld在文件IO中陷入困境,从表t的MyISAM数据文件中的随机偏移读取。我甚至不明白为什么要阅读那个文件。

我可以想到两种可能的解释:

  1. 即使在它知道存在主键冲突之后,它也必须查看将要更新的字段中的内容 - 如果它恰好是目标值,在这种情况下为0,它将不会执行更新 - 即受影响的零行。
  2. 此外,当您更新字段时,我相信MySQL会将整行重新写回磁盘(如果不是因为分页而导致多行),而不是只是那个单个字段可能会假设
  3.   

    但如果我创建没有col4的t,那么POP 2和POP 3非常快。为什么呢?

    如果它是一个固定行大小的MyISAM表,由于表中的数据类型,它看起来像是CHAR字段,即使它是空白的,也会使磁盘上的表大75%(每个INT字段4个字节= 16个字节,而CHAR(12)将添加另外12个字节)。所以,理论上,你需要读/写75%以上。

    您的数据集是否适合内存?您是否考虑过使用InnoDB或内存表?

    附录

    如果可用/活动/热数据集从内存中拟合到不适合内存,则性能降低数量级并非闻所未闻。一对夫妇读到:

    http://jayant7k.blogspot.com/2010/10/foursquare-outage-post-mortem.html

    http://www.mysqlperformanceblog.com/2010/11/19/is-there-benefit-from-having-more-memory/