请帮我优化下一个sql查询
SELECT Executor_service.*, Executor.*
FROM Executor_service
INNER JOIN Executor ON Executor.user_id = Executor_service.executor_id
LEFT JOIN Cancel ON Cancel.executor_id = Executor.user_id AND Cancel.city_id = 3538
WHERE Cancel.order_id IS NULL
AND Executor.user_id != 236
AND Executor_service.service_id = 511
AND Executor_service.status = 'free'
AND Executor_service.mstatus = 'work'
AND Executor_service.city_id =3538
AND Executor.balance > 0
AND Executor.status = 'free'
ORDER BY Executor.rate DESC
LIMIT 1
这个代码非常慢(10-15s)->>左连接cancel on cancel.executor\u id=executor.user\u id和cancel.city\u id=3538
更新1
我需要获取executor.user\u id
表执行器具有下一个结构执行器
表executor\u service是have next struct executor\u service
表cancel是具有下一个结构cancel
表executor是系统中存在的所有executors。
表executor\u service是每个executor的exist服务,其中executor.user\u id=executor\u service.executor\u id
表cancel是关于取消订单的存在信息(取消人和原因)
我需要从指定的城市获取一个具有最高评级(而不是零余额)的executor,该城市根据executor\u service表(executor\u service.service\u id)中的指定id执行服务。同时,cancel表不应包含给定执行器为此服务被点击的记录
更新2
我改变了
SELECT Executor_service.*, Executor.*
FROM Executor_service
INNER JOIN Executor ON Executor.user_id = Executor_service.executor_id
到
SELECT Executor.user_id
FROM Executor
INNER JOIN Executor_service ON Executor.user_id = Executor_service.executor_id
需要3-5秒,但查询时间太长了。
3条答案
按热度按时间k3fezbri1#
尝试索引:
executor_service(city_id, service_id, status, mstatus, user_id)
.我猜
join
键已具有索引。iqjalb3h2#
稍微重新构造了查询。我更喜欢看表“a”直接连接到“b”和“b”到“c”的位置,等等。。我还尝试将left side table.column保留在左侧,将left side table.column保留在右侧。另外,对于特定于表的条件,我尝试将其直接放在连接处。这有助于我形象化的条件是什么,什么可能有助于确定优化指标。。。
也就是说,有一对可传递的关系(如果a=b和b=c,那么a=c),比如您对executor的userid的标准,它与executor\u service.executor\u id相同,所以我把它移到“es”(executor\u service的别名)的where子句中。在左侧更正cancel代码的连接,并在where中显式查找is null。
至于索引,我将确保以下内容对您有所帮助
通过在索引中包含余额,使得查询的覆盖索引不需要转到数据页,并且可以直接从索引中获取值。
uinbv5nw3#
因为你没有从你计划的表中选择任何东西
LEFT JOIN
,完全可以省略。使用INNER JOIN
过滤你的结果,但是LEFT (OUTER) JOIN
没有,所以没有必要:看看是否适合你。如果你真的打算用
LEFT JOIN
在Cancel
比这更好的方法。性能优化的问题在于,您当前并没有真正使用
LEFT JOIN
完全。如果您真的想使用left join,就不能在where子句中使用表的列。把那个连接变成内部连接。另一件小事:看看代码,最好是连接表
Cancel
以及Executor_service
通孔city_id
列而不是写入city_id =3538
两次:带有这些更正的代码如下(保留
Cancel
中的表INNER JOIN
,就像以前一样):另外,如果你想使用
LEFT JOIN
筛选结果以便排除Cancel
表(如注解中所述),则可以使用以下代码:或者,您可以使用
LEFT JOIN
(添加了Cancel.order_id
然后移动WHERE Cancel.order_id IS NULL
外部查询中的条件。热释光;博士:
如果你真的想在
Cancel
你可以把它全部省略。如果要将其用作排除连接到中现有数据的数据Cancel
表,然后您应该重写它作为在上一个代码中发布的(或通过子查询)。如果没有这些-这是很难优化代码不知道背后的数据。。。在这种情况下,我至少希望这些小小的输入能帮助你更好地理解你真正想要的和得到的。