質問: クエリを並列実行すると、ほぼ空のテーブルを結合すると、MySQL のパフォーマンスが低下するのはなぜですか?
以下は、私が直面している問題のより詳細な説明です。MySQL に 2 つのテーブルがあります
CREATE TABLE first (
num int(10) NOT NULL,
UNIQUE KEY key_num (num)
) ENGINE=InnoDB
CREATE TABLE second (
num int(10) NOT NULL,
num2 int(10) NOT NULL,
UNIQUE KEY key_num (num, num2)
) ENGINE=InnoDB
最初のレコードには約 1,000 件のレコードが含まれています。2 番目のレコードは空であるか、レコードがほとんど含まれていません。また、問題に何らかの形で関連する二重インデックスも含まれています。問題は単一インデックスで解消されます。現在、これらのテーブルに対して多くの同一のクエリを並行して作成しようとしています。各クエリは次のようになります。
SELECT first.num
FROM first
LEFT JOIN second AS second_1 ON second_1.num = -1 # non-existent key
LEFT JOIN second AS second_2 ON second_2.num = -2 # non-existent key
LEFT JOIN second AS second_3 ON second_3.num = -3 # non-existent key
LEFT JOIN second AS second_4 ON second_4.num = -4 # non-existent key
LEFT JOIN second AS second_5 ON second_5.num = -5 # non-existent key
LEFT JOIN second AS second_6 ON second_6.num = -6 # non-existent key
WHERE second_1.num IS NULL
AND second_2.num IS NULL
AND second_3.num IS NULL
AND second_4.num IS NULL
AND second_5.num IS NULL
AND second_6.num IS NULL
私が得ている問題は、8 コア マシンでパフォーマンスがほぼ直線的に上昇するのではなく、実際には低下していることです。つまり、プロセスが 1 つの場合、1 秒あたりの通常のリクエスト数は約 200 です。予想される代わりに 2 つのプロセスを使用すると、1 秒あたり最大 300 - 400 クエリまで増加します。実際には 150 に減少します。10 プロセスの場合、クエリは 70 しかありません。毎秒。テストに使用している Perl コードを以下に示します。
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use Parallel::Benchmark;
use SQL::Abstract;
use SQL::Abstract::Plugin::InsertMulti;
my $children_dbh;
foreach my $second_table_row_count (0, 1, 1000) {
print '#' x 80, "\nsecond_table_row_count = $second_table_row_count\n";
create_and_fill_tables(1000, $second_table_row_count);
foreach my $concurrency (1, 2, 3, 4, 6, 8, 10, 20) {
my $bm = Parallel::Benchmark->new(
'benchmark' => sub {
_run_sql();
return 1;
},
'concurrency' => $concurrency,
'time' => 3,
);
my $result = $bm->run();
}
}
sub create_and_fill_tables {
my ($first_table_row_count, $second_table_row_count) = @_;
my $dbh = dbi_connect();
{
$dbh->do(q{DROP TABLE IF EXISTS first});
$dbh->do(q{
CREATE TABLE first (
num int(10) NOT NULL,
UNIQUE KEY key_num (num)
) ENGINE=InnoDB
});
if ($first_table_row_count) {
my ($stmt, @bind) = SQL::Abstract->new()->insert_multi(
'first',
['num'],
[map {[$_]} 1 .. $first_table_row_count],
);
$dbh->do($stmt, undef, @bind);
}
}
{
$dbh->do(q{DROP TABLE IF EXISTS second});
$dbh->do(q{
CREATE TABLE second (
num int(10) NOT NULL,
num2 int(10) NOT NULL,
UNIQUE KEY key_num (num, num2)
) ENGINE=InnoDB
});
if ($second_table_row_count) {
my ($stmt, @bind) = SQL::Abstract->new()->insert_multi(
'second',
['num'],
[map {[$_]} 1 .. $second_table_row_count],
);
$dbh->do($stmt, undef, @bind);
}
}
}
sub _run_sql {
$children_dbh ||= dbi_connect();
$children_dbh->selectall_arrayref(q{
SELECT first.num
FROM first
LEFT JOIN second AS second_1 ON second_1.num = -1
LEFT JOIN second AS second_2 ON second_2.num = -2
LEFT JOIN second AS second_3 ON second_3.num = -3
LEFT JOIN second AS second_4 ON second_4.num = -4
LEFT JOIN second AS second_5 ON second_5.num = -5
LEFT JOIN second AS second_6 ON second_6.num = -6
WHERE second_1.num IS NULL
AND second_2.num IS NULL
AND second_3.num IS NULL
AND second_4.num IS NULL
AND second_5.num IS NULL
AND second_6.num IS NULL
});
}
sub dbi_connect {
return DBI->connect(
'dbi:mysql:'
. 'database=tmp'
. ';host=localhost'
. ';port=3306',
'root',
'',
);
}
そして、パフォーマンスの向上と同時に実行されるこのような比較クエリの場合:
SELECT first.num
FROM first
LEFT JOIN second AS second_1 ON second_1.num = 1 # existent key
LEFT JOIN second AS second_2 ON second_2.num = 2 # existent key
LEFT JOIN second AS second_3 ON second_3.num = 3 # existent key
LEFT JOIN second AS second_4 ON second_4.num = 4 # existent key
LEFT JOIN second AS second_5 ON second_5.num = 5 # existent key
LEFT JOIN second AS second_6 ON second_6.num = 6 # existent key
WHERE second_1.num IS NOT NULL
AND second_2.num IS NOT NULL
AND second_3.num IS NOT NULL
AND second_4.num IS NOT NULL
AND second_5.num IS NOT NULL
AND second_6.num IS NOT NULL
テスト結果、CPU およびディスク使用率の測定値は次のとおりです。
* テーブル `first` には 1000 行あります * テーブル `second` には 6 つの行があります: `[1,1],[2,2],..[6,6]` クエリの場合: SELECT first.num 最初から LEFT JOIN second AS second_1 ON second_1.num = -1 # 存在しないキー LEFT JOIN second AS second_2 ON second_2.num = -2 # 存在しないキー LEFT JOIN second AS second_3 ON second_3.num = -3 # 存在しないキー LEFT JOIN second AS second_4 ON second_4.num = -4 # 存在しないキー LEFT JOIN second AS second_5 ON second_5.num = -5 # 存在しないキー LEFT JOIN second AS second_6 ON second_6.num = -6 # 存在しないキー WHERE second_1.num IS NULL AND second_2.num IS NULL AND second_3.num IS NULL AND second_4.num IS NULL AND second_5.num IS NULL AND second_6.num IS NULL 結果: 同時実行数: 1、速度: 162.910/秒 同時実行数: 2、速度: 137.818/秒 同時実行数: 3、速度: 130.728/秒 同時実行数: 4、速度: 107.387/秒 同時実行数: 6、速度: 90.513/秒 同時実行数: 8、速度: 80.445 / 秒 同時実行数: 10、速度: 80.381/秒 同時実行数: 20、速度: 84.069/秒 6 つのプロセスでクエリを実行した最後の 60 分間のシステム使用量: $ iostat -cdkx 60 avg-cpu: %user %nice %system %iowait %steal %idle 74.82 0.00 0.08 0.00 0.08 25.02 デバイス: rrqm/s wrqm/sr/sw/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util sda1 0.00 0.00 0.00 0.12 0.00 0.80 13.71 0.00 1.43 1.43 0.02 sdf10 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 10.00 5.00 0.02 sdf4 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 30.00 15.00 0.05 sdm 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sdf8 0.00 0.00 0.00 0.37 0.00 1.24 6.77 0.00 5.00 3.18 0.12 sdf6 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 10.00 5.00 0.02 sdf9 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 0.00 0.00 0.00 SDF 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sdf3 0.00 0.00 0.00 0.08 0.00 1.33 32.00 0.00 4.00 4.00 0.03 sdf2 0.00 0.00 0.00 0.17 0.00 1.37 16.50 0.00 3.00 3.00 0.05 sdf15 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sdf14 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sdf1 0.00 0.00 0.00 0.05 0.00 0.40 16.00 0.00 0.00 0.00 0.00 sdf13 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 10.00 5.00 0.02 sdf5 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 50.00 25.00 0.08 sdm2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sdm1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sdf12 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 10.00 5.00 0.02 sdf11 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 10.00 5.00 0.02 sdf7 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 10.00 5.00 0.02 md0 0.00 0.00 0.00 0.97 0.00 13.95 28.86 0.00 0.00 0.00 0.00 #################################################### ############################### クエリの場合: SELECT first.num 最初から LEFT JOIN second AS second_1 ON second_1.num = 1 # 既存のキー LEFT JOIN second AS second_2 ON second_2.num = 2 # 既存のキー LEFT JOIN second AS second_3 ON second_3.num = 3 # 既存のキー LEFT JOIN second AS second_4 ON second_4.num = 4 # 既存のキー LEFT JOIN second AS second_5 ON second_5.num = 5 # 既存のキー LEFT JOIN second AS second_6 ON second_6.num = 6 # 既存のキー WHERE second_1.num は NULL ではありません AND second_2.num IS NOT NULL AND second_3.num IS NOT NULL AND second_4.num IS NOT NULL AND second_5.num IS NOT NULL AND second_6.num IS NOT NULL 結果: 同時実行数: 1、速度: 875.973/秒 同時実行数: 2、速度: 944.986/秒 同時実行数: 3、速度: 1256.072/秒 同時実行数: 4、速度: 1401.657/秒 同時実行数: 6、速度: 1354.351/秒 同時実行: 8、速度: 1110.100/秒 同時実行数: 10、速度: 1145.251/秒 同時実行数: 20、速度: 1142.514/秒 6 つのプロセスでクエリを実行した最後の 60 分間のシステム使用量: $ iostat -cdkx 60 avg-cpu: %user %nice %system %iowait %steal %idle 74.40 0.00 0.53 0.00 0.06 25.01 デバイス: rrqm/s wrqm/sr/sw/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util sda1 0.00 0.00 0.00 0.02 0.00 0.13 16.00 0.00 0.00 0.00 0.00 sdf10 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 10.00 5.00 0.02 sdf4 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 10.00 5.00 0.02 sdm 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sdf8 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 10.00 5.00 0.02 sdf6 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 0.00 0.00 0.00 sdf9 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 10.00 5.00 0.02 SDF 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sdf3 0.00 0.00 0.00 0.13 0.00 2.67 40.00 0.00 3.75 2.50 0.03 sdf2 0.00 0.00 0.00 0.23 0.00 2.72 23.29 0.00 2.14 1.43 0.03 sdf15 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sdf14 0.00 0.00 0.00 0.98 0.00 0.54 1.10 0.00 2.71 2.71 0.27 sdf1 0.00 0.00 0.00 0.08 0.00 1.47 35.20 0.00 8.00 6.00 0.05 sdf13 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sdf5 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 10.00 5.00 0.02 sdm2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sdm1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sdf12 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sdf11 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 0.00 0.00 0.00 sdf7 0.00 0.00 0.00 0.03 0.00 1.07 64.00 0.00 10.00 5.00 0.02 md0 0.00 0.00 0.00 1.70 0.00 15.92 18.74 0.00 0.00 0.00 0.00 #################################################### ############################### また、このサーバーには多くの空きメモリがあります。トップの例: トップ - 19:02:59 アップ 4:23、4 ユーザー、負荷平均: 4.43、3.03、2.01 タスク: 合計 218、実行中 1、睡眠中 217、停止 0、ゾンビ 0 CPU: 72.8%us、0.7%sy、0.0%ni、26.3%id、0.0%wa、0.0%hi、0.0%si、0.1%st メモリ: 合計 71701416k、使用済み 22183980k、空き 49517436k、バッファ 284k スワップ: 合計 0k、使用済み 0k、空き 0k、キャッシュ 1282768k PID ユーザー PR NI VIRT RES SHR S %CPU %MEM TIME+ コマンド 2506 mysql 20 0 51.7g 17g 5920 S 590 25.8 213:15.12 mysqld 9348 topadver 20 0 72256 11m 1428 S 2 0.0 0:01.45 perl 9349 topadver 20 0 72256 11m 1428 S 2 0.0 0:01.44 perl 9350 topadver 20 0 72256 11m 1428 S 2 0.0 0:01.45 perl 9351 topadver 20 0 72256 11m 1428 S 1 0.0 0:01.44 perl 9352 topadver 20 0 72256 11m 1428 S 1 0.0 0:01.44 perl 9353 topadver 20 0 72256 11m 1428 S 1 0.0 0:01.44 perl 9346 topadver 20 0 19340 1504 1064 R 0 0.0 0:01.89 トップ
存在しないキーを使用したクエリでパフォーマンスが低下した理由を知っている人はいますか?