4

設定:

mysql> create table t(a integer unsigned,b integer unsigned);
mysql> insert into t(a,b) values (1,2),(1,3),(2,4);
mysql> create index i_t_a on t(a);
mysql> create index i_t_b on t(b);
mysql> explain select * from t where a=1 or b=4;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t     | ALL  | i_t_a,i_t_b   | NULL | NULL    | NULL |    3 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+

足りないものはありますか?

アップデート

mysql> explain select * from t where a=1 or b=4;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t     | ALL  | i_t_a,i_t_b   | NULL | NULL    | NULL | 1863 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+

バージョン

mysql> select version();
+----------------------+
| version()            |
+----------------------+
| 5.1.36-community-log |
+----------------------+

MySQLでインデックスマージを正常に機能させる人はいますか?

ここで成功した話を見てうれしいです:)

4

3 に答える 3

4

これが実際の理由であるかどうかはわかりませんが、そのソルトに値するDBMSは、「rows = 3」プロパティを参照し、インデックスを確認するだけの価値がないと判断するだけだと思います。3行で全表スキャンを実行できる速度は、他の方法を無効にします。

数千行で同じことを実行して、同じ結果が得られるかどうかを確認してください。


ここから、コメント投稿者は、「私がテストしたテーブルは、特定の状況でインデックスを使用しないindex-merge-unionバージョンになりました」と述べていますが、それらの状況が正確に何であるかを知らないようです:-)それはおそらく何かですMySQLサポートグループ(および開発者)でもレイズできます。

興味深いことに、次のクエリはEXPLAINから何を提供しますか。

select * from t where a=1
union
select * from t where b=4;

また、MySQLは、テーブル自体のデータに基づいてインデックスユニオンを使用するかどうかを評価している可能性があります。aのバリアントが2つとバリアントが3つしかないb場合でも、クエリが行の大部分を返すと判断される可能性があるため、最適化に煩わされることはありません。

多数の行、および両方の列のさまざまな値の両方aを試すことができbます。

これはMySQLの知識に基づくものではなく、コードベースを見たり、製品を使用したことはありません。しかし、私特定の主流のデータベース製品で少し作業をしました-したがって、このアドバイスは、物事を効率的に行うための理解に基づいています。これは、MySQLには特に当てはまらない可能性があり、実際にはまったく当てはまらない可能性があります。 :-)

于 2010-03-25T03:44:04.307 に答える
2

長いバック:

lesssongからのインデックスを表示します。

Table, Non_unique, Key_name, Seq_in_index, Column_name, Collation, Cardinality, Sub_part, Packed, Null, Index_type, Comment
'lesssong', 0, 'PRIMARY', 1, 'S_ID', 'A', 50000, , '', '', 'BTREE', ''
'lesssong', 1, 'idx_s_name', 1, 'S_NAME', 'A', 25000, 10, '', '', 'BTREE', ''
'lesssong', 1, 'idx_S_ARID', 1, 'S_ARID', 'A', 1315, , '', '', 'BTREE', ''
'lesssong', 1, 'idxFTS', 1, 'S_NAME', '', 1, , '', '', 'FULLTEXT', ''

カウント=50000

select * from lesssong where s_name='kv'またはs_arid=4を説明する

1, 'SIMPLE', 'lesssong', 'index_merge', 'idx_s_name,idx_S_ARID,idxFTS', 'idx_s_name,idx_S_ARID', '12,4', '', 2, 'Using sort_union(idx_s_name,idx_S_ARID); Using where'

構造:

'S_ID', 'int(10) unsigned', 'NO', 'PRI', '', 'auto_increment'
'S_ALID', 'int(10) unsigned', 'NO', '', '', ''
'S_ARID', 'int(10) unsigned', 'NO', 'MUL', '', ''
'S_NAME', 'varchar(100)', 'NO', 'MUL', '', ''
'S_LYRIC', 'text', 'NO', '', '', ''
'S_WRITER', 'varchar(45)', 'NO', '', '', ''
'S_LINK', 'varchar(255)', 'NO', '', '', ''

あなたの構造でさえ、私はそれが私のために働くようになりました:

ランダムに100個の値を追加しました:

insert into t(a,b) select ceil(rand()*5),ceil(rand()*30)

select *fromtを説明します。ここでa=1またはb=4;

id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
1, 'SIMPLE', 't', 'index_merge', 'i_t_a,i_t_b', 'i_t_a,i_t_b', '5,5', '', 32, 'Using union(i_t_a,i_t_b); Using where'
于 2010-04-05T08:50:41.867 に答える
0

MySQLにマージを強制的に使用させる方法がないのは残念です。たとえば、デフォルトで間違ったインデックスを選択しているときに特定のインデックスを強制的に使用する方法があります(めったに起こりませんが、私はそれを見て対処しなければなりませんでした) 。

index_mergeは言うまでもなく、MySQLがインデックスを使用する価値があると判断するのに十分なカーディナリティがデータにないからだと思います。1800行は何もありません-本当に。少なくとも100万行を作成し、それらすべてを一意にします。その後、それはおそらくあなたが望むことをするでしょう。このような小さなテーブルでは、インデックスは実際には何もしません。

于 2010-04-07T19:18:29.393 に答える