mysql - UNION vs GROUP BY 或更好的解决方案

标签 mysql sql select group-by union

我有这样一种情况,我在数据库表中有数十万行,假设有 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 中执行此查询,因此第一个是一个衬里,第二个是我需要生成的。

我想知道第二种方法是否正常,也许还有我不知道的第三种方法?

更新:

所有查询中的

columnTwocolumnOne 字段不唯一

例子

# 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/

相关文章:

php - IF EXISTS UPDATE ELSE INSERT 使用 mysql

javascript - 在查询内分配值并且它没有更新

php - 如何获取特定日期范围内的记录

具有可选列过滤器的 MySQL 参数化 SELECT 查询

html - IE6 SELECT HTML 标签导致页面的其余部分消失

php - 从日期时间列获取数据

mysql - 存储语言 (utf8_general_ci)

mysql - 试图让这个 SQL 查询在 phpmyadmin mysql 上运行,但它不起作用

mysql - 显示 2 个不同日期的数据

mysql - SQL 将表列内容复制到条目指定的另一个表列