我有这样一种情况,我在数据库表中有数十万行,假设有 8 列,其中前两列索引(每列两个索引,两列一个复合索引),我有两个带有 group by 和 union 的 SQL 查询:
SELECT MIN(columnOne), columnTwo FROM MyTable
WHERE columnTwo IN (1,2,3)
GROUP BY columnTwo
和
SELECT MIN(columnOne), columnTwo FROM MyTable WHERE columnTwo = 1
UNION
SELECT MIN(columnOne), columnTwo FROM MyTable WHERE columnTwo = 2
UNION
SELECT MIN(columnOne), columnTwo FROM MyTable WHERE columnTwo = 3
似乎第二种方法联合比第一种方法快两倍(有时更多)。
我在 Python 中执行此查询,因此第一个是一个衬里,第二个是我需要生成的。
我想知道第二种方法是否正常,也许还有我不知道的第三种方法?
更新:
所有查询中的columnTwo 和 columnOne 字段不唯一
例子
# columnOne columnTwo
1 a a
2 b b
3 c b
4 d a
...
用 group by 说明查询显示:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE MyTable index secondColIndex,bothColIndex bothColIndex 12 1623713 Using where
Explain for query with union 显示:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY MyTable ref secondColIndex,bothColIndex bothColIndex 4 const 217472 Using where
2 UNION MyTable ref secondColIndex,bothColIndex bothColIndex 4 const 185832 Using where
3 UNION MyTable ref secondColIndex,bothColIndex bothColIndex 4 const 175572 Using where
UNION RESULT <union1,2,3> ALL Using temporary
MyTable 中的索引:
Table, Non_unique, Key_name, Seq_in_index, Column_name, Collation, Cardinality, Sub_part, Packed, Null, Index_type, Comment, Index_comment
MyTable, 0, PRIMARY, 1, Id, A, 1623713, , , , BTREE, ,
MyTable, 1, columnOneIndex, 1, columnOne, A, 1623713, , , , BTREE, ,
MyTable, 1, columnTwoIndex, 1, columnTwo, A, 5737, , , , BTREE, ,
MyTable, 1, bothColumnsIndex, 1, columnTwo, A, 5171, , , , BTREE, ,
MyTable, 1, bothColumnsIndex, 2, columnOne, A, 1623713, , , , BTREE, ,
最佳答案
您所看到的是由于 MySQL 优化器的限制(在最新版本中可能有很大改进)。 GROUP BY
几乎总是会导致文件排序,从而限制索引的使用。
一个替代方案本质上只是 UNION
版本的简化,但使用相关子查询:
SELECT x.columnTwo,
(SELECT MIN(columnOne)
FROM myTable t
WHERE t.columnTwo = x.columnTwo
) as min_columnOne
FROM (SELECT 1 as columnTwo UNION ALL
SELECT 2 as columnTwo UNION ALL
SELECT 3 as columnTwo
) x;
这应该与使用 UNION
的版本具有基本相同的性能。相关子查询应该使用索引进行计算。
关于mysql - UNION vs GROUP BY 或更好的解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47471521/