Mysql 即使所有相关列都已编制索引,添加ORDER BY也会显著降低联接查询的速度。我怎样才能使它更快?
我有以下联接查询:Mysql 即使所有相关列都已编制索引,添加ORDER BY也会显著降低联接查询的速度。我怎样才能使它更快?,mysql,join,sql-order-by,query-optimization,Mysql,Join,Sql Order By,Query Optimization,我有以下联接查询: SELECT table1.*, table2.* FROM Table1 AS table1 LEFT JOIN Table2 AS table2 USING (col1) LEFT JOIN Table3 as table3 USING (col1) WHERE 3963.191 * ACOS( (SIN(PI() * $usersLatitude / 180) * S
SELECT
table1.*,
table2.*
FROM
Table1 AS table1
LEFT JOIN
Table2 AS table2
USING
(col1)
LEFT JOIN
Table3 as table3
USING
(col1)
WHERE
3963.191 *
ACOS(
(SIN(PI() * $usersLatitude / 180) * SIN(PI() * table3.latitude / 180))
+
(COS(PI() * $usersLatitude / 180) * COS(PI() * table3.latitude / 180) * COS(PI() * table3.longitude / 180 - PI() * 37.1092162 / 180))
) <= 10
AND
table1.col1 != '1'
AND
table1.col2 LIKE 'A'
AND
(table1.col3 LIKE 'X' OR table1.col3 LIKE 'X-Y')
AND
(table2.col4 = 'Y' OR table2.col5 = 'Y')
它在3秒内执行
查询中的所有列都被索引,包括表1.col6
中使用的ORDER BY
我试过了,但没有成功
如何使用ORDER BY
快速运行此查询
编辑: 不按
顺序解释扩展的
结果:
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE table1 ALL PRIMARY,col2,col3 NULL NULL NULL 140101 72.61 Using where
1 SIMPLE table2 eq_ref PRIMARY,col4,col5 PRIMARY 4 table1.col1 1 100 Using where
1 SIMPLE table3 eq_ref PRIMARY PRIMARY 4 table1.col1 1 100 Using where
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE table1 ALL PRIMARY,col2,col3 NULL NULL NULL 140101 72.61 Using where; Using filesort
1 SIMPLE table2 eq_ref PRIMARY,col4,col5 PRIMARY 4 table1.col1 1 100 Using where
1 SIMPLE table3 eq_ref PRIMARY PRIMARY 4 table1.col1 1 100 Using where
使用按
顺序解释扩展的的结果:
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE table1 ALL PRIMARY,col2,col3 NULL NULL NULL 140101 72.61 Using where
1 SIMPLE table2 eq_ref PRIMARY,col4,col5 PRIMARY 4 table1.col1 1 100 Using where
1 SIMPLE table3 eq_ref PRIMARY PRIMARY 4 table1.col1 1 100 Using where
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE table1 ALL PRIMARY,col2,col3 NULL NULL NULL 140101 72.61 Using where; Using filesort
1 SIMPLE table2 eq_ref PRIMARY,col4,col5 PRIMARY 4 table1.col1 1 100 Using where
1 SIMPLE table3 eq_ref PRIMARY PRIMARY 4 table1.col1 1 100 Using where
编辑2: 查询中所有列的数据类型(根据要求):
所有3个表(表1、表2和表3)都是
MyISAM
这不是一个解决方案,但可能会有所帮助:避免使用“*”指定所需的列,并显式指定它们。当您使用*来指定所有列时,MySQL在对数据进行排序时,需要做更多的工作来分流数据,因此更有可能进行文件排序,这很慢
此外,索引对MySQL排序数据的容易程度几乎没有影响,尽管您应该检查它是否使用了BTREE索引,因为它们更有可能保持相对良好的排序
最糟糕的是,如果您还没有阅读MySQL手册,您可能需要阅读一下手册中的内容。我看不到任何适用的内容,但您可能会看到我缺少的内容。我唯一可以考虑的解决方法是将表更改为默认的order by,然后将查询中的
order by一起删除
如果您的查询速度与您指示的一样快,我希望它返回的数据集相当小。如果是这样的话,我会按原样包装你的,然后把订单放在外面,比如
select
PreQuery.*
from
( Your Entire Query Without the order by clause ) as PreQuery
order by
PreQuery.Col6 Desc
这样,外部查询与现有索引无关,只返回数据。。。然后,该结果将按照原始结果应用顺序
希望这能为您解决问题。除了我的另一个答案外,我还提供了一个选择,将您现有的查询包装在一个选择中,然后对结果排序。这里是查询的另一个选项。。。如果我的解释不正确,请纠正我
您正在对表2进行左连接,但需要Col4或Col5='Y',因此由于where子句,指示内部连接(记录必须存在于表1和表2上)
同样地,在表3中加入了表1,但限制了距离为什么要对非通配符值执行类似的操作?这将使规划者更加悲观。但最重要的是,您需要查看查询计划器显示的内容
另外,您最近是否对表格进行了分析
?如果行统计信息关闭,计划员将做出错误的选择。您看过执行计划了吗?可能是您指定的索引没有覆盖查询或未被使用。我怀疑“喜欢”的操作员可能与此有关it@Charleh:我如何看待执行计划?如果为查询中使用的每一列指定了索引,那么我指定的索引如何不覆盖查询或不被使用?提前感谢您提供的更多信息。请查看MySql文档页面。试试看,看看是否使用了索引,这是唯一可以确定的方法!另请看-一个很好的信息是:通过获取EXPLAIN输出的rows列中的值的乘积,您可以很好地指示连接有多好。这应该大致告诉您MySQL执行查询必须检查多少行。如果使用max_join_size系统变量限制查询,则此行乘积还用于确定要执行的多个table SELECT语句以及要中止的语句。请参阅第8.11.2节“调整服务器参数”。
因此,请尝试使用或不使用“排序依据”,并检查results@Charleh:好的,现在进行解释,包括和不包括命令,并将在稍后发布结果。谢谢。我同意你说的,但在这种情况下没什么区别。例如,我没有选择表1.*,而是选择表2.*
我只是尝试了selecttable1.col1
,但仍然花了3秒钟。如果你还有其他想法,请告诉我。谢谢不,我累坏了。我将编辑答案以提及MySQL手册中关于优化orderby
的页面,但我看到其中有很多可能会有所帮助。谢谢。对不起,我帮不上忙了。你提出的解决方案和这个解决方案不一样吗?如果是这样,那么正如我在主要帖子中提到的,该解决方案并没有提高查询速度。还有其他想法吗?那是我希望避免的最后手段。你知道为什么简单地添加ORDER BY会使查询的长度增加10倍以上吗?因为默认的顺序是按主键,而在另一列上对其重新排序需要filesort,这在本质上是相当慢的。在上面添加DESC命令会进一步降低速度。简单地说,MySQL有很多工作要做,因为这一切。奇怪的是,我在我的网站上的其他几个地方使用ORDER BY DESC,但它并没有像这个查询那样让它慢下来。这个查询有一个特定的原因,它会随着ORDERBY的出现而显著减慢。这是我希望在这里解开的一个谜非常有趣,谢谢!我将对此进行一次尝试并报告。排序结果的ORDER BY
在哪里?@程序员,我只需在没有Where的情况下进行一次快速测试,看看它与您的原始结果(没有ORDER BY)相比如何,然后,像往常一样在Where子句后添加ORDER BY。好的,我尝试了,没有您建议的索引,而且速度也没有提高。你能给我看看你的SQL代码吗
SELECT STRAIGHT_JOIN
T1.*,
T2.*
FROM
Table1 AS T1
JOIN Table2 AS T2
ON T1.Col1 = T2.Col1
AND ( T2.Col4 = 'Y' OR T2.Col5 = 'Y' )
JOIN Table3 as T3
ON T1.Col1 = T3.Col1
AND 3963.191
* ACOS( (SIN(PI() * $usersLatitude / 180) * SIN(PI() * T3.latitude / 180))
+ ( COS(PI() * $usersLatitude / 180) * COS(PI() * T3.latitude / 180)
* COS(PI() * table3.longitude / 180 - PI() * 37.1092162 / 180)
)
) <= 10
WHERE
T1.Col2 LIKE 'A'
AND ( T1.col3 LIKE 'X' OR T1.col3 LIKE 'X-Y')
AND T1.Col1 != '1'
ORDER BY
T1.Col6
On Table 1, I would have an index on ( Col2, Col3, Col1, Col6 )
On Table 2 on ( Col1, Col4, Col5 )
On Table 3 on ( Col1 ) <-- assume already had this.