我有一个查询目的是查找表item_location中的记录,并且在一年中的特定月份不存在于表operation_detail中
SELECT il.item_id,
il.SEQUENCE,
SUM (il.quantity) AS quantity,
i.buy_price,
i.sell_price, i.item_name, i.unit_measure_id,
i.is_raw_item AS is_raw
FROM item_location il, item i
WHERE il.quantity <> 0
AND il.item_id = i.item_id
AND il.SEQUENCE = i.SEQUENCE
AND NOT EXISTS (
SELECT od.*
FROM operation_detail od, operation_header oh, rt_operation o
WHERE od.item_id = il.item_id
AND od.SEQUENCE = il.SEQUENCE
AND od.operation_header_id = oh.operation_header_id
AND oh.operation_type_id = o.operation_type_id
AND o.operation_stock IN ('I', 'O')
AND MONTH (oh.operation_date) = @MONTH
AND YEAR (oh.operation_date) = @YEAR)
GROUP BY il.item_id,
il.SEQUENCE,
i.buy_price,
i.sell_price,
i.item_name,
i.unit_measure_id,
i.is_raw_item
请注意,使用.net
从DataAdapter
平台运行此查询会产生超时,从SQL运行它需要40秒
我的主要问题是TimeOut ....任何建议
答案 0 :(得分:2)
运行查询的默认超时为30秒,如果命令需要更长时间,则会终止。我想你应该优化你的查询以更快地运行,但你也可以增加数据适配器的超时时间:
dataAdapter.SelectCommand.CommandTimeout = 120; // Two minutes
答案 1 :(得分:0)
每当我看到包含多个分组列的查询时,我开始认为可以重写查询。通常,您应该尝试仅对键列进行分组,将键和聚合结果存储到临时表中,然后加入该临时表以获取其他详细信息。例如:
insert into
#tmp
select
key1, key2, sum(things)
from
table;
然后:
select
table.key1, table.key2,
tmp.sum_of_all_things,
table.other_stuff, table.extra_data
from
#tmp tmp
join
table on tmp.key1 = table.key1 and tmp.key2 = table.key2
这将避免必须对所有非键列进行排序的所有开销(这是group by
操作的一部分)。
其次,由于not exists
子句中有相关子查询,因此应在匹配谓词上提供一个或多个索引(在本例中为item_id
和sequence
)。 exists
的工作方式,如果结果集包含任何行,它将返回true,但它仍然需要为外部查询的每一行重新执行内部查询。所以你需要索引才能减少这种折磨。
由于你的内部查询本身包含3个连接,我会认真考虑单独运行它并将结果存储在另一个临时表中。
答案 2 :(得分:0)
为了提高性能,请不要使用非SARGable where子句。你的主要错误是什么使查询非SARGable直接在WHERE子句的列上的函数。这不会使用索引。
查看此示例,其中声明查询强制INDEX SEEK操作的新参数
DECLARE @YEAR int = 1971,
@MONTH int = 11,
@StartDate datetime,
@EndDate datetime
SELECT @StartDate = CAST(CAST(@YEAR AS nvarchar(4)) + RIGHT('0' + CAST(@MONTH AS nvarchar(2)), 2) + '01' AS datetime),
@EndDate = DATEADD(month, 1, CAST(@YEAR AS nvarchar(4)) + RIGHT('0' + CAST(@MONTH AS nvarchar(2)), 2) + '01')
SELECT
...
WHERE od.item_id = il.item_id
AND od.SEQUENCE = il.SEQUENCE
AND od.operation_header_id = oh.operation_header_id
AND oh.operation_type_id = o.operation_type_id
AND o.operation_stock IN ('I', 'O')
AND oh.operation_date >= @StartDate AND oh.operation_date < @EndDate