-1

SpecialOffersと呼ばれる特別オファーアイテムのテーブルとテーブルSOItems があり、特定のアイテムが見つかったら特別オファーを取得したいので、最初にこれを行いました:

IF EXISTS(SELECT * FROM SOTtems WHERE ItemType = 2 AND Itemid = @id)
BEGIN
      INSERT INTO #SO
      SELECT * FROM SpecialOffers so 
      INNER JOIN SOItems soi ON so.Id = soi.SpecialOfferID
      WHERE soi.ItemType = 2 AND soi.Itemid = @id
END

しかし、その後、INNER JOIN を取り除くために、パフォーマンスが向上すると考えたので、次のようにしました。

DECLARE @specialOfferID INT

SET @specialOfferID = (SELECT SpecialOfferID FROM SOTtems WHERE ItemType = 2 AND Itemid = @id)

IF @specialOfferID IS NOT NULL
BEGIN
     INSERT INTO #SO
     SELECT * FROM SpecialOffers so 
     WHERE ID = @specialOfferID
END

したがって、より多くのSQLクエリを実行するか、この例と一般的に結合を使用するのに、どちらがより効率的でパフォーマンスが優れていますか

注:私が書いているストアドプロシージャでは、これを6回以上行う必要があるため、uに尋ねました:)

ありがとう

4

2 に答える 2

1

オプティマイザーはこれを処理できる以上の能力があるため、この手の最適化は不要である可能性があります。

両方を SSMS に入れて一緒に実行し、実行計画で相対的なコストを調べることができます。

通常、結合を回避することは、最適化の最初のステップではありません。

通常、私の最初のステップは、インデックス作成戦略を調べて、基本的なインデックスを除外していないことを確認してから、実行計画を調べて、明らかな問題がないかどうかを確認することです。

次に、実際のパフォーマンスの問題が発生するまで最適化を行いません。実際にパフォーマンスの問題を引き起こしている原因を理解した後でのみです。

実際には、次のように単純化します。

INSERT INTO #SO
SELECT *
FROM SpecialOffers so 
INNER JOIN SOItems soi
    ON so.Id = soi.SpecialOfferID
    AND soi.ItemType = 2
    AND soi.Itemid = @id

それだけです-EXISTSチェックなどはありません-内部結合は、存在のチェックが冗長であることを意味します。これは、それ以外の場合は何も挿入されないためです。これにより、条件が変更された場合に条件を複製する必要がなくなり、結合内のコードが誤って変更される可能性が低くなるため、ある意味では保守しやすいコードになります。一方、結合が変更された場合、より深刻な影響が生じる可能性があります。

EXISTS チェックを使用しなくても、これを WHERE バージョンとして記述できることに注意してください。

通常、コードが少ないということは、バグが隠れる場所が少ないことを意味します。

于 2012-04-22T13:10:05.580 に答える
1

Management Studio のウィンドウに両方のクエリを貼り付け、クエリの実行プランを表示します。それは何が起こっているかを正確に教えてくれます。

ほとんどの場合、パフォーマンスの違いはほとんどないことがわかります。2 番目のほうが多少速くなる可能性があるのは、 がないことですが、IF EXISTS(...)一方でその結果はキャッシュされるため、違いはまだ小さいです。

違いを生むもう 1 つのことは#SO、最初のクエリでより多くのデータをテーブルに入れることです。を使用してSELECT *いると、必要以上のデータが取得されます。たとえば、フィールドSOItems.SpecialOfferIDとの両方SpecialOffers.Idが含まれていますが、常に同じであることがわかっています。必要以上にフェッチしないように、返すフィールドを指定します。

于 2012-04-22T13:12:00.863 に答える