0

私は非常に単純な MYSQL データベースを持っていますが、列は 3 つしかありませんが、数百万行あります。列のうちの 2 つ (hid1、hid2) は調査オブジェクト (約 50,000 個) を記述し、3 番目の列 (スコア) は hid1 と hid2 の比較の結果です。したがって、行数は max(hid1)*max(hid2) となり、かなり大きな数になります。テーブルは 1 回だけ書き込み、何百万回も読み取る必要があるため、MyISAM テーブルを選択しました (これが良いアイデアだったと思います)。最初は、特定の hid1、hid2 のペアの「スコア」を取得する予定でしたが、特定の hid1 のすべてのスコア (および hid2) を取得する方が便利であることが判明しました。

私のテーブル(「結果」)は次のようになります。

+-------+-----------------------+------+-----+---------+-------+
| Field | Type                  | Null | Key | Default | Extra |
+-------+-----------------------+------+-----+---------+-------+
| hid1  | mediumint(8) unsigned | YES  | MUL | NULL    |       |
| hid2  | mediumint(8) unsigned | YES  |     | NULL    |       |
| score | float                 | YES  |     | NULL    |       |
+-------+-----------------------+------+-----+---------+-------+

典型的なクエリは次のようになります

select hid1,hid2,score from result where hid1=13531 into outfile "/tmp/ttt"

問題は次のとおりです。クエリに時間がかかりすぎることがあります。少なくとも場合によってはそうです。一部の「hid1」値では、結果が 1 秒以内に返されます。他の hid1 (特に大きな数字の場合) では、最大 40 秒待たなければなりません。前述したように、これらのクエリを何千回も実行する必要があるため、処理を高速化することに関心があります。

繰り返しますが、クエリには約 50,000 件のヒットがあり、特定の順序でヒットする必要はありません。ここで何か間違ったことをしていますか、それとも MySQL のようなリレーショナル データベースはこのタスクに対応していませんか?

私がすでに試したことは、/etc/mysql/my.conf の key_buffer を増やすことです。hid1 のインデックスは数 GB ですが、有効にするには key_buffer をインデックス サイズよりも大きくする必要がありますか?

ヒントをいただければ幸いです。


編集:対応する「説明」出力で実行される例を次に示します。

select hid1,hid2,score from result where hid1=132885 into outfile "/tmp/ttt"
Query OK, 16465 rows affected (31.88 sec)

以下に示すように、インデックス hid1_idx が実際に使用されています。

mysql> explain select hid1,hid2,score from result where hid1=132885 into outfile "/tmp/ttt";
+----+-------------+--------+------+---------------+------------+---------+-------+-------+-------------+
| id | select_type | table  | type | possible_keys | key        | key_len | ref   | rows  | Extra       |
+----+-------------+--------+------+---------------+------------+---------+-------+-------+-------------+
|  1 | SIMPLE      | result | ref  | hid1_index    | hid1_index | 4       | const | 15456 | Using where |
+----+-------------+--------+------+---------------+------------+---------+-------+-------+-------------+

セットで 1 行 (0.00 秒)

私が困惑しているのは、hid1 の数値が小さいクエリは常に、数値が大きいクエリよりもはるかに高速であるという事実です。これは、インデックスの使用に期待するものではありません。

4

3 に答える 3

2

常に等価フィルタ on を含むクエリ パターンに基づく 2 つのランダムな提案hid1:

  1. 代わりに InnoDB テーブルを使用し、上のクラスター化インデックスを利用してください(hid1, hid2)。そうすれば、同じ hid に属するすべての行が物理的に一緒に配置され、取得高速化されます。

  2. 適切なパーティション数で、hid1 のテーブルをハッシュ パーティション化します。

于 2013-05-13T12:13:06.520 に答える
1

そのようなクエリを最適化する最も簡単な方法は、インデックスを使用することです。みたいな簡単なこと

alter table results add index(hid1)

送信したクエリを改善します。さらに、一度に両方のフィールドで検索したい場合は、インデックスで両方のフィールドを使用できます。

alter table results add index(hid1, hid2)

そうすれば、MySQL は非常に整理された方法で結果にアクセスし、必要な情報を見つけることができます。

最初のクエリで Explain を実行すると、次のように表示される場合があります。

| select_type | table  | type|possible_keys| rows   |Extra
| SIMPLE      | results| ALL |             | 7765605| Using where

インデックスを追加すると、次のように表示されます

| select_type | table  | type|possible_keys| rows   |Extra
| SIMPLE      | results| ref |hid1         | 2816304|

これは、最初のケースではすべての行をチェックする必要があり、2 番目のケースではrefを使用して情報を見つけることができることを示しています。

于 2013-05-13T11:41:34.633 に答える