2

テーブル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秒かかることに注意してください

私の主な問題はタイムアウトです....任意の提案

4

3 に答える 3

2

クエリを実行するためのデフォルトのタイムアウトは30秒であり、コマンドにさらに時間がかかる場合は、コマンドが終了します。クエリを最適化して実行速度を上げる必要があると思いますが、データアダプタのタイムアウトを増やすこともできます。

dataAdapter.SelectCommand.CommandTimeout = 120; // Two minutes
于 2013-03-27T07:26:42.167 に答える
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に1つまたは複数のインデックスを指定する必要があります。この方法は機能し、結果セットに行が含まれている場合はtrueを返しますが、外部クエリのすべての行に対して内部クエリを再実行する必要があります。したがって、これをそれほど厄介なものにするためのインデックスが必要になります。item_idsequenceexists

内部クエリ自体には3つの結合が含まれているため、個別に実行して結果を別の一時テーブルに保存することを真剣に検討します。

于 2013-03-27T07:41:03.123 に答える
0

パフォーマンスを向上させるために、SARGable以外のwhere句を使用しないでください。クエリを非SARGableにする主な間違いは、WHERE句の列に直接関数があることです。これはインデックスを使用しません。

INDEXSEEK操作を強制するクエリの新しいパラメータを宣言するこの例を見てください。

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 
于 2013-03-27T10:03:52.623 に答える