我必须在MySQL查询中加入大表,这需要很长时间 - 大约180秒。有没有优化合并的提示?
我的桌子有10个字段。我只在查询中使用4 - 所有字符串。表有大约600,000行,结果应该有大约50行。
使用的四行是:标题,变量,位置,日期
这是我的问题:
SELECT DISTINCT t1.Title, t1.Variables FROM `MyTABLE` t1 JOIN `MyTABLE` t2
USING (Title, Variables)
WHERE (t1.Location, t1.Date) = ('Location1', 'Date1')
AND (t2.Location, t2.Date) = ('Location2', 'Date2')
答案 0 :(得分:8)
像其他人指出的那样,你需要适当的索引。对于此特定查询,您可以从以下索引中受益:
(Location, Date
)或(Date, Location
)(对于WHERE
子句)
和
(Title, Variables
)或(Variables, Title
)(针对join
条件,ON
条款)
确切地知道位置,日期,标题和变量列的大小(即数据类型)会很有帮助,因为大索引可能比小索引慢。
最后,只是一个提示:我不会像你那样使用花哨的比较结构。
USING (Title, Variables)
可能没问题,但我肯定会检查是否
(t1.Location, t1.Date) = ('Location1', 'Date1')
和
(t2.Location, t2.Forecast_date) = ('Location2', 'Date2')
表现得像你期望的那样。所以我肯定会在其上运行EXPLAIN
,并将输出与“常规”旧式比较进行比较,如下所示:
t1.Location = 'Location1'
AND t1.Date = 'Date1'
AND t2.Location = 'Location2'
AND t2.Forecast_date = 'Date2'
你可能会在逻辑上争论,它是一样的,它应该没关系 - 你是对的。但话说回来,MySQL的优化器并不是很聪明,并且总是存在错误的可能性,特别是对于没有经常使用的功能。我认为这是一个特色。所以我至少会尝试解析并查看这些替代符号是否被评估相同。
但是BenoKrapo指出,做这样的事情会不容易:
SELECT Title, Variables
FROM MyTABLE
WHERE Location = 'Location1' AND Date = 'Date1'
OR Location = 'Location2' AND Date = 'Date2'
GROUP BY Title, Variables
HAVING COUNT(*) >= 2
编辑:我将HAVING COUNT(*) = 2
更改为HAVING COUNT(*) >= 2
。见评论(再次感谢,BenoKrapo)
编辑:发布此答案后的几天,我发现Facebook的MySQL架构师Mark Callaghan的这篇文章:http://www.facebook.com/note.php?note_id=243134480932 从本质上讲,他描述了由于MySQL优化器错误,类似但不同的“智能”比较如何提供极差的性能。所以我的观点是,当你受苦时尝试不用语法,你可能遇到了一个错误。
答案 1 :(得分:2)
是。根据针对所涉及的表运行的查询创建适当的索引。
答案 2 :(得分:2)
您可以使用“EXPLAIN”预先添加SQL语句,然后重新运行它,这可能是因为您正在加入的列上缺少索引。
还尝试使用STRAIGHT_JOIN并提及左侧大小较慢的表,右侧较大的表提示MySQL选择第一个表。
答案 3 :(得分:1)
确保您匹配的字段已编入索引。 匹配数值也比字符串快。
但是编写
并不简单SELECT DISTINCT
Title,
Variables
FROM `MyTABLE`
WHERE
Location = 'Location1' AND Date = 'Date1'
OR
Location = 'Location2' AND Date = 'Date2'
答案 4 :(得分:1)
这可能有点作弊,但实际上我发现在查询之后在PHP中将两个查询连接在一起更容易。这只能起作用,因为我选择了两个不同的变量。
$query = "SELECT DISTINCT Title, Variables FROM
MyTABLE WHERE Location='Location1' AND Variable='Variable1'";
$result = mysql_result($query);
while ($row = mysql_array_assoc($result)) {
$Title = $row['Title'];
$Variables = $row['Variables'];
$Array_result1[$Title] = $Variables;
}
$query = "SELECT DISTINCT Title, Variables FROM
MyTABLE WHERE Location='Location2' AND Variable='Variable2'";
$result = mysql_result($query);
while ($row = mysql_array_assoc($result)) {
$Title = $row['Title'];
$Variables = $row['Variables'];
$Array_result2[$Title] = $Variables;
}
$Array_result = array_intersect($Array_result1, $Array_result2);
我喜欢只使用一个MySQL查询来合并这两个查询的想法,但这要快得多。
答案 5 :(得分:0)
如果没有表格和查询的描述,我们可以提供帮助。
有几件事可以决定加入的速度。
另外,请查看EXPLAIN query
,它将查看mysql执行它所需的所有步骤。它可以帮助你。
答案 6 :(得分:0)
尝试在where子句中的列上使用复合索引,并尝试将所有其他列放入包含列中的select中,这将节省传统的查找成本。
答案 7 :(得分:0)
我使用union运算符进行了两次单独的连接和组合结果。我及时得到了很好的改善。
SELECT t1.Title, t1.Variables FROM
{MyTable的{1}} {MyTable的{1}} {MyTable的{1}} {MyTable的{1}}
确保两个查询的列数相同,每列的数据类型相同。另外,检查select子句的顺序。