web-dev-qa-db-ja.com

内部結合テーブルの複合インデックス?

以下のクエリを高速化するために、追加のインデックスを作成しようとしています。すべてのキーは主キー(テーブル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を使用するため)優れていますか?または両方を使用できますか?

3
spacing

いくつかの考え:

私はあなたの既存のスキーマを知りませんが、あなただけのクエリから離れて、テーブルAで(address, code)の追加複合インデックスと(address, code, user)の複合インデックスを試します。

これは、複合インデックスは常に、クエリ内でのWHERE- ingまたはJOIN- ingの正しい順序である必要があるためです。

以下の節でWHEREと言った場合、これらはJOINsにも適用できます。 2つのテーブルを一緒にJOINする場合、エンジンはON句に基づいて適切な行を検索する必要があるため、それらを同等のものと考える必要があります。

これが最良のインデックスを見つけるためのアルゴリズムです(これは Rick James のインデックスクックブックです):

  1. WHERE column = 'foo'を含むクエリ内の列を任意の順序で

  2. 次に、以下の3つのオプションから1つを選択します。

    a。範囲が選択されている列(例: WHERE column > 'foo' AND column < 'bar'

    b。 GROUP BYの列は、ASC/DESCの混合を提供していません

    c。 ORDER BYの列は、ASC/DESCの混合を提供していません

また、idはテーブルAのPKですか?その場合、PKは常にMySQLのすべてのインデックスの末尾に追加されることに注意してください。これらの列を他のインデックスに追加する必要はありません。エンジンが自動的に追加します。

2
jonbaldie