3

次のクエリがあります。

SELECT
  tl.*, d.*
FROM
  TrackerLocations AS tl
  inner join Trackers t on tl.TrackerId = t.TrackerId
  inner join Devices d on t.UserId = d.UserId
WHERE
  tl.ReceivedTime = (SELECT MAX(tl2.ReceivedTime) FROM TrackerLocations tl2 WHERE tl2.TrackerId = tl.TrackerId)
  and tl.ReceivedTime >= DATEADD (MINUTE,-2,GETUTCDATE())
  and d.OSType <> 3
  and d.Notify = 1

...そして驚いたことに、許容できる時間内に結果が返されません。実稼働環境で初めて実行したときは、実行に 3 秒ほどかかりました。現在、タイムアウト (C# アプリケーション内では 30 秒) まで実行されます。
主な目的は、「トラッカーからの最新の場所と、ユーザーのデバイスに関する情報を 2 分間さかのぼって提供する」ことです。
このクエリの最適化に関するヒントはありますか?

ありがとう!

インデックス: どこでも句の列 (ReceivedTime、OSType、Notify)。

実行計画については、とても大きなことで、私にはあまりなじみがありません。ここに貼り付けるべきですか?:)

4

5 に答える 5

2

TrackerId( 、ReceivedTime)のインデックスを試してみることをお勧めしReceivedTimeます。しかし、プロファイリングと実際の実行計画がなければ、それはただの闇のショットです。

于 2013-08-09T17:49:44.163 に答える
1

過去 2 分間の最新の ReceivedTime を探しているのでReceivedTime、DESC 順にインデックスを作成する必要があります。DESC オーダー部分は重要です。MAX関数にも役立ちます。でインデックスを試すこともできます(ReceivedTime DESC, TrackerID)

于 2013-08-09T18:23:59.520 に答える
1

このクエリの実行計画がどのように見えるかわからないため、結果を高速化するのに役立つと思われる方法しか実行できません。

  1. 主キーと外部キーの制約はありますか
  2. それらのキーはインデックス化されますか

それを超えて、CTEを使用して、結合される結果を制限して、(テストされていません)の効果にします。

;WITH cte_loc AS
(
    SELECT
        tl.*
    FROM
        TrackerLocations tl            
    WHERE
        tl.ReceivedTime >= DATEADD (MINUTE,-2,GETUTCDATE())
),cte_loc2 AS
(
    SELECT
        TrackerId
        ,MAX(ReceivedTime) AS MaxReceivedTime
    FROM
        cte_loc
    GROUP BY
        TrackerId
),cte_dev AS
(
    SELECT
        tl.TrackerId,
        d.*
    FROM
        cte_loc2 tl 
            INNER JOIN Trackers t ON tl.TrackerId = t.TrackerId
            INNER JOIN Devices d ON t.UserId = d.UserId             
    WHERE
        d.OSType <> 3 AND d.Notify = 1
)

SELECT
    tl.*, d.*
FROM
    cte_loc AS tl      
        INNER JOIN cte_loc2 tl2 ON tl.TrackerId = tl2.TrackerId
                               AND tl.ReceivedTime = tl2.MaxReceivedTime
        LEFT JOIN cte_dev d ON tl.TrackerId = d.TrackerId
于 2013-08-09T18:09:38.417 に答える
1

TrackerLocations.TrackerIdとにインデックスを作成しますTrackers.TrackerId。またDevices.UserIdTrackers.UserId2番目のJOINTrackerLocations.ReceivedTime最後に、WHERE節の索引の作成についても見てみましょう。

一般に、このようなクエリを最適化するために最初に検討するのは、結合条件にインデックスがあるかどうかを確認することです。また、何らかのフィルター (WHERE句) がある場合は、インデックスを追加する別の場所になる可能性があります。

クエリの実行計画を見ずに、どこを最適化する必要があるかを正確に判断することは困難です。各テーブルにいくつのレコードがあるかなど、多くの要因が影響を与える可能性があります。ただし、インデックスの作成に夢中にならないでください。たとえば、新しいデータを挿入するときなど、インデックスはパフォーマンスに影響します。最良のアドバイスは、さまざまなインデックスでテストして、実行計画からヒントが得られるかどうかを確認することです。

于 2013-08-09T17:51:10.847 に答える