奇妙な振る舞いに遭遇します。次の構造を持つ2つのテーブルproduct
とproduct_description
があります(簡潔にするために、いくつかの無関係な列は省略されています)。
CREATE TABLE `oc_product` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`price` decimal(15,4) NOT NULL DEFAULT '0.0000',
PRIMARY KEY (`product_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `oc_product_description` (
`product_id` int(11) NOT NULL,
`language_id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
`description` text NOT NULL,
PRIMARY KEY (`product_id`,`language_id`),
KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
language_id
には2つの可能な値があるため、各製品にはproduct_description
テーブルに正確に2つの対応する行があります。次のクエリを実行すると、product_description rows
の値に驚きました。
EXPLAIN
SELECT p.product_id
FROM oc_product p
JOIN oc_product_description pd USING (product_id)
WHERE p.product_id = 12345;
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | p | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | Using index |
| 1 | SIMPLE | pd | NULL | ref | PRIMARY | PRIMARY | 4 | const | 60 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
主キーはそのままで問題ないはずですが、好奇心から、product_description
列に対してのみproduct_id
に単一のインデックスを追加しました。
ALTER TABLE `oc_product_description` ADD INDEX (`product_id`);
Explainクエリを再試行して異なる結果が得られましたが、奇妙なことに、同じキーが使用されています。
+----+-------------+-------+------------+-------+--------------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+--------------------+---------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | p | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | Using index |
| 1 | SIMPLE | pd | NULL | ref | PRIMARY,product_id | PRIMARY | 4 | const | 2 | 100.00 | Using index |
+----+-------------+-------+------------+-------+--------------------+---------+---------+-------+------+----------+-------------+
次に、追加のインデックスを削除します。
ALTER TABLE `oc_product_description` DROP INDEX `product_id`;
そして、同じクエリを再度実行します。
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | p | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | Using index |
| 1 | SIMPLE | pd | NULL | ref | PRIMARY | PRIMARY | 4 | const | 2 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
突然、行数が通常に戻りました。同じデータベースのバックアップを使用して、同じ動作を再現することができました。以前にOPTIMIZE TABLE oc_product_description
とREPAIR TABLE oc_product_description
の両方を試しましたが、60
に追加のインデックスを追加(および削除)するまで、以前と同じproduct_id
行数です。 。
一体何がここで起こっているのか誰かが説明できますか? MySQL Serverバージョン5.7.18-0ubuntu0.16.04.1-log(Ubuntu)を使用しています
本当にInnoDBに切り替える必要があります。 MyISAMには、ここ数年、実質的に何の努力も払われていません。
「2」と「60」は大きく違うことに同意します。ただし、残りのEXPLAIN
出力は、その数に基づいて何も変更されていないことを意味します。
あなたの質問はかなり人工的です。 1つの製品のすべての翻訳を取得しますが、これは役に立たないようです。また、すでに知っている情報(product_id)も取得します。実際のクエリに切り替えてください。その時何か面白いことがあるかもしれません。