有没有人成功地为MySQL进行索引合并工作?

时间:2010-03-25 03:37:28

标签: mysql sql-optimization

设定:

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做过索引合并工作?

我很高兴在这里看到成功的故事:)

3 个答案:

答案 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个变体,它可能会再次确定您的查询将返回大部分行,因此不需要进行优化。

您可以在ab列中同时使用大量行来尝试各种各样的值。

请记住,这不是基于我对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行没什么 - 真的。创建至少一百万行,并使其中每一行都是唯一的。然后它可能会做你想要的。有了这么小的表,索引并没有真正为你做任何事情。