【问题标题】:A performance question in MySQLMySQL 中的性能问题
【发布时间】:2010-12-02 19:18:27
【问题描述】:

我在 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 2 和 3 INSERT INTO ... SELECT ... ON DUPLICATE KEY UPDATE 查询使用 mysqld 运行得非常快 占用 100% 的核心,而在其他时间 mysqld 以 1% 的 CPU 读取 t.MYD,即表 t 的 MyISAM 数据文件,以随机偏移量陷入困境。

我很难确定在哪些情况下它是快速和 虽然速度很慢,但我发现了一个可重复的案例:

在上述序列中,POP 2 和 3 非常慢。但是,如果我创建 t 没有 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 文件之前使用 sort(1),我能够大大减少整体处理时间。

【问题讨论】:

  • 你想做什么 - 请直接回答!!
  • 它正在读取该文件,因为您正在插入该文件?
  • @f00:我正在尝试将 TSV 文件摄取到表中,如 OP 的第二和第三句中所述。
  • @Danosaure:看起来是这样。在 POP 2 INSERT 的前半小时左右,所有磁盘 IO 都是(随机偏移)从我要插入的表的数据文件中读取的。几个小时后,它是读取和写入的混合体。
  • @fsb:也许不相关......但我看到我的生产服务器在 MySQL 5.0.x 上运行的双 CPU 64 位比单 CPU 少 32 位 RAM 慢(具有相同的在 my.cnf 中设置)。 5.1.x 不会发生这种情况您是否可以在另一台服务器上尝试此操作以查看是否发生相同的模式?

标签: mysql performance optimization


【解决方案1】:

这是一个非常开放的问题......这是一个投机的、开放的答案。 :)

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

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

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

但是如果我在没有 col4 的情况下创建 t,那么 POP 2 和 POP 3 会非常快。为什么?

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

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

附录

如果可用/活动/热数据集从适合内存变为不适合内存,则性能下降数量级并非闻所未闻。一对夫妇写道:

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/

【讨论】:

  • 有趣的 cmets。谢谢。行大小是固定的。数据并不都适合内存。这是一个一次,经常阅读的应用程序。我不认为这两种情况(有和没有 col4)之间的行长差异可以作为答案。这是每行 20 字节和 32 字节之间的差异。性能差异大约是 50 或 100 X。在快速情况下,在 5 分钟内插入 2000 万行,在慢速情况下,这是一个工作日的大部分时间。
猜你喜欢
  • 2019-09-20
  • 1970-01-01
  • 2016-09-05
  • 2016-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多