Mysql 提高两个联合(UNION ALL)大型表中的SELECT性能

Mysql 提高两个联合(UNION ALL)大型表中的SELECT性能,mysql,union,Mysql,Union,我有两个巨大的表,需要执行以下查询。表authors_1(约2000万行)和authors_2(约1.2亿行)的结构相同。我做了研究,提出了以下查询和表结构。查询仍然需要很长时间(通常在10到20秒之间) 以下是查询: SELECT `fname`, `lname` FROM ( SELECT `fname`, `lname` FROM `authors_1` WHERE 1 AND `lname` LIKE 'AR%' UNION ALL SE

我有两个巨大的表,需要执行以下查询。表
authors_1
(约2000万行)和
authors_2
(约1.2亿行)的结构相同。我做了研究,提出了以下查询和表结构。查询仍然需要很长时间(通常在10到20秒之间)

以下是查询:

SELECT `fname`, `lname` 
FROM (
    SELECT `fname`, `lname` 
    FROM `authors_1` 
    WHERE 1 AND `lname` LIKE 'AR%' 
    UNION ALL 
    SELECT `fname`, `lname` 
    FROM `authors_2` 
    WHERE 1 AND `lname` LIKE 'AR%') `a` 
GROUP BY CONCAT(`fname`, `lname`) 
ORDER BY `lname` 
LIMIT 0, 999;
这就是结构,这两个表的结构相似(
FT
索引用于其他查询)

这是上面显示的示例查询的
EXPLAIN
输出(我不知道如何使其美观,我正在使用PMA):

1主系统所有476968使用临时系统;使用文件排序
2个派生作者\u 1范围lname\u 4,名称,lname名称386 184800使用where
3联合作者2范围lname 4,名称,lname 386 292168使用where
联合结果所有使用临时

有改进此查询/结构的建议吗?

尝试将
按CONCAT分组(fname,lname)
更改为
按fname,lname分组。执行所有这些连接都是多余的工作,这是不必要的

它们之间唯一的语义区别是,如果有两个人的名字和姓氏不同,但在连接时是相同的,例如,Freda Smith和Fred Asmith。这样的组合可能不太可能,我怀疑您是否真的希望首先将它们组合成一个结果

如果您按所选的同一组列进行分组,则只需使用

SELECT DISTINCT fname, lname

您可以使用
UNION DISTINCT
而不是
UNION ALL
,因为您希望删除重复项。然后您不需要在外部查询中进行分组或
DISTINCT

我认为您不需要
lname\u 4
索引,因为它是
名称
索引的前缀。请注意,将使用
名称
索引。有多少行符合
LIKE
标准?将GROUP BY CONCAT(
fname
lname
)更改为GROUP BY
fname
lname
,然后mysql可以使用索引(如果有)+我已经做了我的研究,并提出了……
在询问之前进行研究,所以这总是一个好兆头
:-)
。并且还显示了一个
解释
。@Barmar,对于给定的查询,它大约有320K行。我认为
lname\u 4
会有所帮助,因为它只索引了前4个字母。B树索引可以用来优化索引的任何前缀。因此,前缀的另一个索引是多余的。建议使用
UNION DISTINCT
的索引为+1。需要明确的是,如果您这样做,则无需执行
分组依据
选择不同的
。谢谢,我已将其从“还”改为“改为”,并添加了更多解释。@Barmar,我测试了您提出的解决方案。它确实提高了执行时间(根据PMA显示的时间,从53秒提高到25秒),但仍然需要很长时间。还有什么地方需要改进吗?其他搜索查询显示出不同的执行时间,有时甚至更短。我从来没有真正理解使用
TINYTEXT
的意义,因为您可以使用
VARCHAR(255)
来完成相同的任务,并且不必绕过文本类型的限制。
1   PRIMARY <derived2>  ALL                 476968  Using temporary; Using filesort 
2   DERIVED authors_1   range   lname_4,name,lname  name    386     184800  Using where 
3   UNION   authors_2   range   lname_4,name,lname  name    386     292168  Using where 
    UNION RESULT    <union2,3>  ALL                     Using temporary 
SELECT DISTINCT fname, lname