在大型表上运行SELECT的存储过程超时。 where子句导致超时,因为我只选择另一个表中的城市。
AND city IN (SELECT DISTINCT city from tOH where clientId = @clientId)
AND state IN (SELECT DISTINCT state from tOH where clientId = @clientId)
*注意几乎总是只返回一个州
我正在尝试将城市放入一个表格,然后使用该表格来填充城市,但我收到的错误是@cities未被声明。
DECLARE @cities TABLE
(
city varchar(200)
);
INSERT INTO @cities (city) SELECT city FROM tOH WHERE clientId = @clientId GROUP BY city
然后我的where子句改为
AND city IN (SELECT city from @cities)
有人能找到优化此存储过程的好方法吗?
----------------------------更新------------------ ------------------
连接速度太慢了。我认为具有临时表或表变量的解决方案将起作用。
答案 0 :(得分:8)
不仅速度慢,而且不正确。
假设您的城市是“威斯康星州埃文斯维尔”,但您的tOH
表只有“Evansville,IN”和“密尔沃基,威斯康星州”的条目。您目前单独检查城市和州的部分,因此您现有的查询将找到“Evansville”和“WI”的匹配项。它将允许这个城市,即使它真的不应该。
请改为:
INNER JOIN
(
SELECT DISTINCT City AS tOHCity, State AS tOHState
FROM tOH
WHERE ClientID= @ClientID
) cs ON cs.tOHCity = city AND cs.tOHState = state
请注意,子查询基于以下假设:原始帖子中的DISTINCT是必需的,因为每个客户端可能在该表中有多个相同的城市。如果不是这种情况,您可以直接加入tOH
表。
将此与正确的索引相结合,你应该很好。
答案 1 :(得分:4)
我会在tOH表上尝试JOIN并通过clientid过滤整个查询。您也可以使用SELECT INTO将其放入临时表中。
答案 2 :(得分:4)
来自SQL Hacks:
当子查询不包含时 聚合函数,很有可能 不需要子查询 - 你需要一个 JOIN。
因此,您应该将第一个子查询(AND CITY IN)转换为JOIN。除非您向我们提供剩下的查询,否则我们无法准确地向您展示如何,但它的基础是将City添加为您在主查询中选择的表。
答案 3 :(得分:4)
我认为值得指出遭遇超时背后的原因。您的查询从原始表中选择每一条记录,然后对于它选择的每条记录,它必须为每条记录反复查询同一表中的DISTINCT城市列表。
答案 4 :(得分:1)
您可能希望查看在State列上放置索引,但是您应该对此进行一些基准测试。在插入新行时,您必须权衡索引的好处与成本。
您可能还想对City列执行相同的操作。
答案 5 :(得分:1)
使用EXISTS代替IN
AND EXISTS(SELECT 1 FROM tOH WHERE tOH.city=main.city AND clientId=@clientId)
您还需要确保在两个表格中对该城市编制索引。
答案 6 :(得分:1)
你可能已经尝试过了,但我的第一反应是使用你的城市填充临时表。这可能是你正在做的事情,我只是不熟悉语法,但我一直在使用:
Create Table #Cities(City varchar(200))
然后你将在你的例子中填写临时表和查询(INSERT INTO ...和AND city IN(从#Cities中选择城市))
答案 7 :(得分:1)
我假设关于tOH的DISTINCT的原因是城市名称可能存在于多个州,同样,由于每个州都有多个城市,因此州有多次出现。
如果每个城市和州的组合是一个独特的事件,那么放弃DISTINCT并做类似以下的事情会更合适和更具成本效益:
select mytable.*
from mytable m
inner join tOH t on t.clientid = @clientId
and t.city = m.city and t.state = m.state
答案 8 :(得分:0)
select ....
from ....
inner join tOH ON ...city=tOH.city and ...state=tOH.state
where ... and tOH.clientId = @clientId
答案 9 :(得分:0)
在回答你为什么@cities作为表变量可能不起作用的问题时,你还没有展示sp的其余部分,但我会在某处构建动态SQL并执行它。那个woudl超出了以前存在的表变量的范围。
答案 10 :(得分:0)
您可以使用原始查询(不加入联接),进行下一次更正:
答案 11 :(得分:0)
将您的IN过滤器更改为存在。所以而不是:
AND city IN (SELECT DISTINCT city from tOH where clientId = @clientId)
AND state IN (SELECT DISTINCT state from tOH where clientId = @clientId)
将其更改为:
AND EXISTS (
SELECT 0 FROM tOH t WHERE
ClientID = @clientId
and t.City = parent.ctiy
and t.state = parent.state
)
我已经完成了性能测试,并且总是发现EXISTS的执行速度比IN快。此外,由于你使用同一张桌子进行了两次,所以你获得了双击。
如果可能,您还应该在tOH中为城市和州编制索引。索引是一种参考,因此请确保您了解添加它们的含义。