主キーを使用してMySQLでこれらの単純なSELECTおよびUPDATE要求があり、テーブルには約1,300万行があります。
両方でEXPLAINを実行すると、UPDATEの方が主キーを同じように使用せず、遅いクエリログで遅いと報告されていることに気付きました。
データは次のとおりです。
ご協力ありがとうございました
したがって、クエリオプティマイザのソースコードで範囲を出力する理由を確認する必要がありますが、書き込みの場合、EXPLAINを単純化/制限するために限られた数の書き込みメソッドを使用するだけだと思います。両方のクエリの実際の低行レベルの操作を見ると、SELECT
:
MariaDB [db]> flush status; SELECT `BuyPacker_Email`.`emailOpen` = 1567007592 FROM `BuyPacker_Email` WHERE `BuyPacker_Email`.`emailId` = 17040352; SHOW STATUS like 'Hand%';
Query OK, 0 rows affected (0.000 sec)
1 row in set (0.000 sec)
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Handler_commit | 1 |
| Handler_delete | 0 |
| Handler_discover | 0 |
| Handler_external_lock | 0 |
| Handler_icp_attempts | 0 |
| Handler_icp_match | 0 |
| Handler_mrr_init | 0 |
| Handler_mrr_key_refills | 0 |
| Handler_mrr_rowid_refills | 0 |
| Handler_prepare | 0 |
| Handler_read_first | 0 |
| Handler_read_key | 1 | <----
| Handler_read_last | 0 |
| Handler_read_next | 0 |
| Handler_read_prev | 0 |
| Handler_read_retry | 0 |
| Handler_read_rnd | 0 |
| Handler_read_rnd_deleted | 0 |
| Handler_read_rnd_next | 0 |
| Handler_rollback | 0 |
| Handler_savepoint | 0 |
| Handler_savepoint_rollback | 0 |
| Handler_tmp_delete | 0 |
| Handler_tmp_update | 0 |
| Handler_tmp_write | 0 |
| Handler_update | 0 |
| Handler_write | 0 |
+----------------------------+-------+
27 rows in set (0.001 sec)
...単一の行の読み取りとインデックス付けを行います。そして更新のために:
MariaDB [db]> FLUSH STATUS; UPDATE `BuyPacker_Email` SET `BuyPacker_Email`.`emailOpen` = 1567007592 WHERE `BuyPacker_Email`.`emailId` = 17040352; SHOW STATUS like 'Hand%';
Query OK, 0 rows affected (0.000 sec)
Query OK, 0 rows affected (0.000 sec)
Rows matched: 1 Changed: 0 Warnings: 0
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Handler_commit | 2 |
| Handler_delete | 0 |
| Handler_discover | 0 |
| Handler_external_lock | 0 |
| Handler_icp_attempts | 0 |
| Handler_icp_match | 0 |
| Handler_mrr_init | 0 |
| Handler_mrr_key_refills | 0 |
| Handler_mrr_rowid_refills | 0 |
| Handler_prepare | 2 |
| Handler_read_first | 0 |
| Handler_read_key | 1 | <-----
| Handler_read_last | 0 |
| Handler_read_next | 0 |
| Handler_read_prev | 0 |
| Handler_read_retry | 0 |
| Handler_read_rnd | 0 |
| Handler_read_rnd_deleted | 0 |
| Handler_read_rnd_next | 0 |
| Handler_rollback | 0 |
| Handler_savepoint | 0 |
| Handler_savepoint_rollback | 0 |
| Handler_tmp_delete | 0 |
| Handler_tmp_update | 0 |
| Handler_tmp_write | 0 |
| Handler_update | 1 | <----
| Handler_write | 0 |
+----------------------------+-------+
27 rows in set (0.000 sec)
...まったく同じ読み取り戦略+必要な書き込みを使用してレコードを更新します。
したがって、必要以上に多くのレコードを読み取るというオーバーヘッドや、より高価な読み取りプランに関する違いはありません。それがEXPLAIN
の単純化であるか、それとも書き込みクエリによる制限であるかどうか。または、書き込みがどのように機能するかを示し、実際のパフォーマンスへの影響を示すため、実際の違いを示します。 実装の詳細 -に入る必要がありますが、ほとんどの場合、行の列に「1」と表示されている限り、クエリに問題はありません。大まかに言えば、1行の範囲はconstアクセスとほぼ同等であるはずです。