クラスター化インデックスがどのように機能するかについてすべて読んでいて、アプリに役立つと思います。主キーが自動的にクラスター化インデックスになることは理解していますが、非主キー列にクラスター化インデックスを追加するにはどうすればよいでしょうか?
つまり、ユーザー投稿のデータストアです。各投稿には ID とユーザー ID がありますが、ユーザーは複数回投稿できるため、ユーザー ID は主キーではありません。ユーザー ID にクラスター化インデックスを追加するにはどうすればよいでしょうか。
クラスター化インデックスがどのように機能するかについてすべて読んでいて、アプリに役立つと思います。主キーが自動的にクラスター化インデックスになることは理解していますが、非主キー列にクラスター化インデックスを追加するにはどうすればよいでしょうか?
つまり、ユーザー投稿のデータストアです。各投稿には ID とユーザー ID がありますが、ユーザーは複数回投稿できるため、ユーザー ID は主キーではありません。ユーザー ID にクラスター化インデックスを追加するにはどうすればよいでしょうか。
Clustered and Secondary Indexesによると、テーブルごとにクラスター化インデックスを 1 つだけ持つことができます。
クラスター化インデックス以外のすべてのインデックスは、セカンダリ インデックスと呼ばれます。
テーブルにプライマリ インデックスがなく、別の一意のインデックスがある場合、これがクラスター化インデックスとして使用されます。
テーブルに PRIMARY KEY を定義しない場合、MySQL はすべてのキー カラムが NOT NULL である最初の UNIQUE インデックスを見つけ、InnoDB はそれをクラスター化インデックスとして使用します。
したがって、クラスター化インデックスを自分で追加するのではなく、MySQL がテーブルのプライマリ インデックスまたは最初の一意のインデックスのいずれかをクラスター化インデックスとして選択すると結論付けます。
プライマリまたは一意のインデックスを定義していない場合、MySQL はインデックス自体を作成します
テーブルに PRIMARY KEY または適切な UNIQUE インデックスがない場合、 InnoDB は行 ID 値を含む合成カラムに GEN_CLUST_INDEX という名前の非表示のクラスター化インデックスを内部的に生成します。行は、 InnoDB がそのようなテーブルの行に割り当てる ID によって並べ替えられます。行 ID は 6 バイトのフィールドで、新しい行が挿入されると単調に増加します。したがって、行 ID によって並べ替えられた行は、物理的に挿入順に並んでいます。
@Olaf が説明しているように、InnoDB はどの列または列の組み合わせがクラスター化インデックスになるかを選択します (主キー、または主キーがない場合は最初の一意のインデックス、または 2 つのいずれもない場合は非表示の列)。
一意でない列をクラスター化インデックスとして使用する場合は、を一意のキーとして定義し、クラスター化インデックスとして選択される主キーとpost_id
の組み合わせを作成できます。user_id
post_id
CREATE TABLE Post
( post_id INT NOT NULL AUTO_INCREMENT
, user_id INT NOT NULL
--- other columns
, CONSTRAINT Post_PK
PRIMARY KEY (user_id, post_id) -- your clustered index
, CONSTRAINT post_id_UQ
UNIQUE (post_id) -- you still want uniqueness for the `post_id`
) ENGINE = InnoDB ;
これが良いアイデアであるかどうかは、アプリケーション、データ量、およびクエリによって異なります。一般に、クラスタ化されたキーの最良のプロパティは、一意で、狭く、静的で、増加し続けることです。そのため、自動インクリメント列が最適です。これについては、Kimberly L. Tripp のブログ記事を参照してください。クラスター化インデックスの議論は続く... (SQL-Server に関するものなのでやめないでください。同じ問題が InnoDB のクラスター化インデックス作成に 99% 適用されます)
のようなクラスター化されたキーに(user_id, post_id)
は最初の 3 つのプロパティがありますが、増加し続けるわけではありません。これにより、CI が断片化され、テーブルへの挿入が遅くなる可能性があります。
ただし、必要なデータがクラスター化インデックス内の 1 か所で必要な順序で見つかるため、WHERE user_id = ?
条件、範囲条件WHERE user_id BETWEEN ? AND ?
、またはグループ化を含むより効率的なクエリが得られます。GROUP BY user_id
テストを行って、自分のケースに最適なものを選択することをお勧めします。
1 つのテーブルに複数のクラスター化インデックスを許可する MySQL のバリアントである TokuDB もあります。詳細については、記事を参照してください:複数のクラスタリング インデックスの紹介
InnoDB テーブルの主キーを定義すると、MySQL は主キーをクラスター化インデックスとして使用します。
テーブルの主キーがない場合、MySQL はすべてのキー列が NOT NULL である最初のUNIQUE インデックスを検索し、この UNIQUE インデックスをクラスター化インデックスとして使用します。
InnoDB テーブルに主キーまたは適切な UNIQUE インデックスがない場合、MySQLは、行 ID 値を含む合成列にGEN_CLUST_INDEXという名前の非表示のクラスター化インデックスを内部的に生成します。
間違った質問をしていることをお勧めします。
別の質問の 1 つは、「現在のものを削除しPRIMARY KEY
て、この別のものを「クラスター化」できるようにすることはできますか?」というものです。多くの場合、AUTO_INCREMENT
を削除したり、単純な に変更したりできますINDEX
。
より可能性の高い質問は、「これに最適なインデックスは何SELECT ...
ですか?」です。他の人は、基本的な MySQL では2 つ目のクラスター化インデックスは問題外であると指摘していますが、次の選択肢は何ですか? が分からないと答えようがありませんSELECT
。しかし、私の Index Cookbookは、大量の の質問に答えますSELECTs
。