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 BYfname
,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