设定:
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做过索引合并工作?
我很高兴在这里看到成功的故事:)
答案 0 :(得分:4)
我不知道这是否是实际的原因,但我认为任何值得盐的DBMS都会看到“rows = 3”属性,并且只是认为即使查看索引也不值得。您可以在三行上执行全表扫描的速度会使任何其他方法无法实现。
尝试用几千行做同样的事情,看看你是否得到相同的结果。
来自here,一位评论者声称“我测试的表导致索引合并联合版本在某些情况下不使用任何索引”,尽管他们似乎不知道这些情况是什么,确切地说:-)这可能是你可以通过MySQL支持小组(和开发人员)提出的。
只是出于兴趣,以下查询从EXPLAIN中提供了什么:
select * from t where a=1
union
select * from t where b=4;
可能是MySQL正在评估是否根据表本身内的数据使用索引联合。如果只有a
的两个变体和b
的3个变体,它可能会再次确定您的查询将返回大部分行,因此不需要进行优化。
您可以在a
和b
列中同时使用大量行和来尝试各种各样的值。
请记住,这不是基于我对MySQL的了解,我从未见过代码库或使用过该产品。但是,我已经对某个主流数据库产品做了一些工作 - 所以这个建议是基于我理解如何有效地做事情,这可能不是MySQL的具体情况,实际上可能根本不是这样的情况: - )
答案 1 :(得分: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,其中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 * from t,其中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'
答案 2 :(得分:0)
太糟糕了,没有办法强迫MySQL使用合并,就像你可以强制它在默认选择错误的时候使用特定的索引(很少发生,但是我已经看过并且不得不处理用它)。
我猜这只是因为你的数据没有足够的基数让MySQL决定值得花时间使用索引,更不用说index_merge了。 1800行没什么 - 真的。创建至少一百万行,并使其中每一行都是唯一的。然后它可能会做你想要的。有了这么小的表,索引并没有真正为你做任何事情。