web-dev-qa-db-ja.com

インデックスと複数列の主キー

検索しましたが、この特定の初心者の質問に対する答えが見つかりませんでした。見逃してしまったらお詫びします。

MySQLデータベースには、次の主キーを持つテーブルがあります

主キーID(請求書、アイテム)

私のアプリケーションでは、「アイテム」自体を選択することも頻繁にあり、「請求書」のみを選択することはあまりありません。これらの列のインデックスからメリットが得られると思います。

以下を定義しても、MySQLは文句を言いません。

INDEX(請求書)、INDEX(アイテム)、PRIMARY KEY id(請求書、アイテム)

しかし、これら2つの列に別々のインデックスが確立されているという証拠は(DESCRIBEを使用して-私が見る方法を知っている唯一の方法で)見ていません。

問題は、主キーを構成する列が自動的に個別にインデックス付けされるかどうかです。また、DESCRIBEよりもテーブルの構造を調べるためのより良い方法はありますか?

32
David Jenings

私はmySqlのインデックスの内部に精通していませんが、私が精通している2つのデータベースベンダー製品(MsSQL、Oracle)では、インデックスはバランスの取れたツリー構造であり、そのノードは列のシーケンスされたタプルとして編成されています。インデックスは(定義されたシーケンス内)で定義されます

したがって、mySqlがそれを非常に異なる方法で行わない限り(おそらくそうではない)、(複数の列にある)任意の複合インデックスは、必要なクエリで使用できます列のリストに互換性がある限り、インデックス内の列のサブセットでフィルタリングまたは並べ替えます。 、列が完全なインデックス内の列のシーケンスされたリストと同じようにシーケンスされた場合、インデックス列の完全なセットの順序付けられたサブセットであり、実際のインデックスシーケンスの最初から始まり、最後を除いてギャップはありません。 .。。

つまり、(a、b、c、d)にインデックスがある場合、(a)、(a、b)、または(a、b、c)でフィルタリングするクエリでもインデックスを使用できます。 、ただし、(b)、(c)、または(b、c)でフィルタリングする必要があるクエリは、インデックスを使用できません。

したがって、あなたの場合、列itemだけでフィルタリングまたはソートする必要がある場合は、別のインデックスを追加する必要があります。その列自体...

44
Charles Bretana

私は個人的に phpMyAdmin を使用してMySQLデータベースの構造を表示および編集しています。これはWebアプリケーションですが、ローカルWebサーバーで十分に実行されます(このマシンとphpPgAdmin用にApacheのインスタンスを実行します)。

(invoice, item)の複合キーは、(invoice, item)およびinvoiceのインデックスのように機能します。 itemだけでインデックスを作成する場合は、そのインデックスを自分で追加する必要があります。 PKはinvoiceでソートされ、次にitemでソートされます。ここで、invoiceは複数のレコードで同じです。複合PKの順序は一意性の強制には関係ありませんが、アクセスには関係します。

あなたのテーブルで私は使用します:

PRIMARY KEY id (invoice, item), INDEX (item)
15
George Steel

テーブルインデックス情報を返すには、次を使用できます。

SHOW INDEX FROM <table>;

参照: http://dev.mysql.com/doc/refman/5.0/en/show-index.html

テーブル情報を表示するには:

SHOW CREATE TABLE <table>;

参照: http://dev.mysql.com/doc/refman/5.0/en/show-create-table.html

主キーはインデックスであるため、追加のインデックスを作成する必要はありません。それらの詳細については、CREATE TABLE構文を参照してください(ここに挿入するには多すぎます)。

http://dev.mysql.com/doc/refman/5.0/en/create-table.html

4
Mike

私はMySQLにあまり詳しくありませんが、一般に、複数列のインデックスは、インデックスの最初の列で、その列だけのインデックスと同じように役立ちます。複数列のインデックスは、列がインデックスに表示されるほど、単一の列に対するクエリにはあまり役立ちません。

複数列のインデックスを階層と考える場合、これはある程度意味があります。インデックスの最初の列は階層のルートであるため、それを検索するには、その最初のレベルをスキャンするだけです。ただし、2番目の列をスキャンするために、データベースは最初の列で見つかった一意の値ごとにツリーを検索する必要があります。これは、ほとんどのオプティマイザがわざわざ複数列のインデックスを調べずに、全表スキャンを選択するのに十分なコストがかかる可能性があります。

たとえば、次のようなテーブルがある場合:

Col1 |Col2 |Col3
----------------
   A |   1 |   Z
   A |   2 |   Y
   A |   2 |   X
   B |   1 |   Z
   B |   2 |   X

3つの列すべてにインデックスがあるとすると、順番に、ツリーは次のようになります。

A
+-1
  +-Z
+-2
  +-X
  +-Y
B
+-1
  +-Z
+-2
  +-X

Col1 = 'A'を探すのは簡単です。2つの順序付けられた値を調べるだけです。ただし、col3 = 'X'を解決するには、4つの大きなバケット内のすべての値を確認する必要があります。各バケットは個別に順序付けられています。

3
Allan

複合インデックスと複合主キーには違いがあります。以下のような複合インデックスを定義した場合

INDEX idx(invoice,item)  

itemに基づいてクエリを実行し、別のインデックスを追加する必要がある場合、インデックスは機能しません

INDEX itemidx(item)  

ただし、以下のような複合主キーを定義した場合

PRIMARY KEY(invoice, item)  

itemに基づいてクエリを実行し、個別のインデックスが必要ない場合、インデックスは機能します。

実例:

mysql>create table test ( col1 int(20), col2 int(20) ) primary key(col1,col2);
mysql>explain select * from test where col2 = 1;
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
|  1 | SIMPLE      | test  | index | NULL          | PRIMARY | 8       | NULL |   10 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
2
cppcoder

Mysqlは、複合キーのインデックスを自動作成します。クエリによっては、複合キーの個々の列に個別のインデックスを作成する必要がある場合があります。

Mysqlワークベンチを使用している場合は、スキーマを手動で右クリックし、[編集]をクリックして、テーブルに関するすべてを表示できます。

0
valentine