1

我正在尝试优化查询。

我的问题似乎与MySQL、Union ALL 和 LIMIT相似,答案可能相同(恐怕)。但是,在我的情况下,有更严格的限制 (1) 以及日期时间列上的索引。

所以我们开始:

为简单起见,让我们只有一个包含三个列的表:

  • md5 (varchar)
  • 值(varchar)。
  • 最后更新(日期时间)

(md5, updated) 上有一个索引,因此在 md5 键上选择,按更新排序并限制为 1 将得到优化。

搜索应返回最多与 10 个 md5 键之一匹配的记录。键具有优先级。因此,如果有 prio 1 的记录,它将优先于 prio 2、3 等的任何记录。

目前使用 UNION ALL:

select * from

(

(
select 0 prio, value
from mytable
where md5 = '7b76e7c87e1e697d08300fd9058ed1db'
order by lastupdated desc 
limit 1
)

union all

(
select 1 prio, value
from mytable
where md5 = 'eb36cd1c563ffedc6adaf8b74c259723'
order by lastupdated desc 
limit 1
)

) x

order by prio
limit 1;

它有效,但如果提供 10 个键,UNION 似乎会执行所有 10 个查询。

但是,从业务角度来看,按顺序运行选择并在第一次匹配后停止是可以的。

这可能是普通的 SQL 吗?

或者唯一的选择是存储过程?

4

3 回答 3

0

优化器UNION ALL无法弄清楚你在做什么。

我不知道您是否可以这样做,但假设您有一个 md5prio 表,其中包含您知道要查找的哈希码列表。例如。

prio   md5
0      '7b76e7c87e1e697d08300fd9058ed1db'
1      'eb36cd1c563ffedc6adaf8b74c259723'
etc

在里面。

那么您的查询可能是:

    select mytable.*
      from mytable
      join md5prio on mytable.md5 = md5prio.md5
  order by md5prio.prio, mytable.lastupdated desc
     limit 1

这可能会保存重复的查询。您肯定需要 mytable.md5 上的索引。我不确定您在 lastupdated 上的复合索引是否会有所帮助;你需要尝试一下。

于 2013-01-03T21:15:09.917 回答
0

有一种更好的方法可以做到这一点,不需要 UNION。您真的想要每个键的分组最大值,并具有自定义排序。

分组最大值

按 FIELD() 排序

于 2013-01-03T21:14:18.370 回答
0

在您的情况下,最有效的解决方案可能是在(md5, lastupdated). 该索引应该用于非常有效地解析每个子查询(查找索引中的值,然后查找一个数据页)。

不幸的是,当有重复的 lastupdated 值时,Gavin 引用的 groupwise max 将产生多行(诚然,在您的情况下可能不是问题)。

实际上,有一种 MySQL 方法可以得到这个答案,使用group_concatand substring_index

select p.prio,
       substring_index(group_concat(mt.value order by mt.lastupdated desc), ',', 1)
from mytable mt join
     (select 0 as prio, '7b76e7c87e1e697d08300fd9058ed1db' as md5 union all
      select 1 as prio, 'eb36cd1c563ffedc6adaf8b74c259723' as md5 union all
      . . .
     ) p
     on mt.md5 = p.md5
于 2013-01-03T21:21:56.580 回答