以下のクエリを高速化するために、追加のインデックスを作成しようとしています。すべてのキーは主キー(テーブルAのidを除く)であるため、すでにデフォルトのbtreeインデックスが関連付けられています。テーブルAのidにもMULキーがあるため、インデックスは既に関連付けられています。これは、一意でないインデックスの一部であることを意味します。
Select A.id
From TableA A
Inner join TableB B
On A.address = B.address
And A.code = B.code
Group by A.id
Having count(distinct B.user) = 1;
これらは、前述のテーブルの現在のインデックスです。
mysql> show index from TableA;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| TableA | 0 | PRIMARY | 1 | address | A | 8 | NULL | NULL | | BTREE | |
| TableA | 0 | PRIMARY | 2 | code | A | 24 | NULL | NULL | | BTREE | |
| TableA | 1 | id | 1 | id | A | 8 | NULL | NULL | | BTREE | |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
mysql> show index from TableB;
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| TableB | 0 | PRIMARY | 1 | user | A | 9 | NULL | NULL | | BTREE | |
| TableB | 0 | PRIMARY | 2 | address | A | 9 | NULL | NULL | | BTREE | |
| TableB | 0 | PRIMARY | 3 | code | A | 9 | NULL | NULL | | BTREE | |
| TableB | 1 | address | 1 | address | A | 9 | NULL | NULL | | BTREE | |
| TableB | 1 | address | 2 | code | A | 9 | NULL | NULL | | BTREE | |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
クエリの説明はこれを述べています:
+----+-------------+-------+--------+---------------+---------+---------+---------------------------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+---------------------------------------+------+----------------------------------------------+
| 1 | SIMPLE | F | index | address | address | 514 | NULL | 9 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | A | eq_ref | PRIMARY | PRIMARY | 514 | db.B.address,db.B.code | 1 | |
+----+-------------+-------+--------+---------------+---------+---------+---------------------------------------+------+----------------------------------------------+
どうすればいいのか理解できません。上記のクエリの速度を向上させるためにできることは、アドレスとコードの複合インデックスだけですか?
または、idのクラスター化インデックスは(クエリがgroup byを使用するため)優れていますか?または両方を使用できますか?
いくつかの考え:
私はあなたの既存のスキーマを知りませんが、あなただけのクエリから離れて、テーブルAで(address, code)
の追加複合インデックスと(address, code, user)
の複合インデックスを試します。
これは、複合インデックスは常に、クエリ内でのWHERE
- ingまたはJOIN
- ingの正しい順序である必要があるためです。
以下の節でWHERE
と言った場合、これらはJOIN
sにも適用できます。 2つのテーブルを一緒にJOIN
する場合、エンジンはON
句に基づいて適切な行を検索する必要があるため、それらを同等のものと考える必要があります。
これが最良のインデックスを見つけるためのアルゴリズムです(これは Rick James のインデックスクックブックです):
WHERE column = 'foo'
を含むクエリ内の列を任意の順序で
次に、以下の3つのオプションから1つを選択します。
a。範囲が選択されている列(例: WHERE column > 'foo' AND column < 'bar'
b。 GROUP BY
の列は、ASC
/DESC
の混合を提供していません
c。 ORDER BY
の列は、ASC
/DESC
の混合を提供していません
また、id
はテーブルAのPKですか?その場合、PKは常にMySQLのすべてのインデックスの末尾に追加されることに注意してください。これらの列を他のインデックスに追加する必要はありません。エンジンが自動的に追加します。