LOAD DATA INFILEを使用してinnodbに挿入された2M行は7.5分かかり、プロファイリングはその時間の99%が"システムロック"であることを示しています。
これは何か役に立つことを教えてくれますか?
mysql> set profiling=1;
Query OK, 0 rows affected (0.00 sec)
mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 1964807 rows affected, 8 warnings (7 min 27.35 sec)
Records: 1964806 Deleted: 1 Skipped: 0 Warnings: 8
mysql> show profile for query 1;
+------------------------------+------------+
| Status | Duration |
+------------------------------+------------+
| starting | 0.000206 |
| checking permissions | 0.000015 |
| Opening tables | 0.000034 |
| System lock | 447.327523 |
| Waiting for query cache lock | 0.000352 |
| query end | 0.000011 |
| closing tables | 0.000014 |
| freeing items | 0.000033 |
| logging slow query | 0.000007 |
| logging slow query | 0.000006 |
| cleaning up | 0.000006 |
+------------------------------+------------+
11 rows in set (0.02 sec)
MySQL Documentation for General Thread States によると==
スレッドは、テーブルの内部または外部システムロックを要求するか、または待機しています。この状態の原因が外部ロックのリクエストであり、同じMyISAMテーブルにアクセスしている複数のmysqldサーバーを使用していない場合は、-skip-external-lockingオプションを使用して外部システムロックを無効にできます。ただし、外部ロックはデフォルトで無効になっているため、このオプションは効果がない可能性があります。 SHOW PROFILEの場合、この状態は、スレッドがロックを要求している(それを待っていない)ことを意味します。
InnoDBは行レベルのロックを行うため、これは驚くべきことではありません。さらに、 gen_clust_index(a.k.a. Clustered Index) では、ある時点で主キーの共有ロックと排他ロックが発生します。
Mysql_load()関数はopen_and_lock_tables()関数を呼び出して、LOAD DATAステートメントで言及されたテーブルをロックします。
MySQLはテーブルに排他ロックを取得するため、テーブルにデータを非常に迅速にロードできます。 LOAD DATAプロセスにはほとんどオーバーヘッドがありません。最低限の解析が行われて機能します。
CONCURRENTオプションはMyISAMテーブルにのみ影響します。InnoDBテーブルにロードしている場合、同時アクセスは許可されません。
システムロックに非常に時間がかかった理由は、実際のデータロードがそのステップのタイミングにまとめられたためです。プロファイラーは、fencepostsの間の時間を測定することで機能します。つまり、エントリー時間は、インストルメント化されたユーザー関数ごとに記録されます。 mysql_lock_tables()関数はmysql_load()内から呼び出されますが、mysql_load()はインストルメント化されていないため、経過時間はシステムロックで始まり、クエリキャッシュロックである次のフェンスポストで終わります。
1.96百万行のデータロードには約447秒かかりました。ロードは計測されていないため、実際のロック時間のオーバーヘッドとロード時間を分離する方法はありません。