1

動的SQLクエリを作成し、exec(@sql)を介して実行するストアドプロシージャがあります。

ストアド プロシージャは、約 12 個のテーブルを結合しています。そのとおり、比較的速く走っていました。しかし、その後、追加のフィールドに追加する必要がありました。これを行うために、次のようなスカラー関数を作成しました。

SELECT @weight = @weight +COUNT(*) FROM dbo.UserPDMedication WHERE UserID = @userid
SELECT @weight = @weight +COUNT(*) FROM dbo.[User] WHERE UserID = @userid AND HoehnYarhID IS NOT null
SELECT @weight = @weight +COUNT(*) FROM dbo.[User] WHERE UserID = @userid AND DateOfBirth IS NOT NULL
SELECT @weight = @weight +COUNT(*) FROM dbo.[User] WHERE UserID = @userid AND GenderID IS NOT NULL
SELECT @weight = @weight +COUNT(*) FROM dbo.[User] WHERE UserID = @userid AND DateDiagnosed IS NOT null

これは基本的に、ユーザーが入力した質問の数に基づいて int を返す単なる関数です。したがって、ストアド プロシージャ内の各ユーザーに対して、この関数が呼び出されます。ストアド プロシージャは次のようになります。

    SELECT DISTINCT u.UserID, u.Healthy, u.DateOfBirth, u.City, st.StateCode AS State, u.GenderID, g.Gender, u.Latitude, u.Longitude, u.PDConditionID, u.Zip, u.Distance,
    (SELECT TOP 1 EmailID FROM Messages m WHERE TrialID = ' + @trialID + ' AND ToUserID = u.userid AND LocationID = ' + @locationID + ') AS MessageID, dbo.UserWeightedValue(u.UserID) as wt
FROM [User] u
    INNER JOIN aspnet_UsersInRoles uir ON u.AspnetUserID = uir.UserId
    INNER JOIN aspnet_Roles r ON uir.RoleId = r.RoleId
    FULL JOIN UserHealthCondition uhc ON u.UserID = uhc.UserID
    FULL JOIN UserMotorSymptom ums ON u.UserID = ums.UserID
    FULL JOIN UserNonMotorSymptom unms ON u.UserID = unms.UserID
    FULL JOIN UserPDMedication updm ON u.UserID = updm.UserID
    FULL JOIN UserPDTreatment updt ON u.UserID = updt.UserID
    FULL JOIN UserSupplement us ON u.UserID = us.UserID
    FULL JOIN UserPDGeneticMarker updgm ON u.UserID = updgm.UserID
    FULL JOIN UserFamilyMember ufm ON u.UserID = ufm.UserID
    FULL JOIN State st ON u.StateID = st.ID
    FULL JOIN Gender g ON u.GenderID = g.ID
WHERE u.UserID IS NOT NULL

(これを短くするためにいくつかのチャンクを削除しました)。この get は、ストアド プロシージャで動的文字列として実行されます。これを最適化して速度を上げる方法に関するヒントはありますか?

ありがとう

編集:ここでの提案の組み合わせを使用して、これを機能させました。複数の select ステートメントを 2 つのステートメントに結合しましたが、関数はそのままにしました。その後、元のストアド プロシージャを取得し、select を ##temp への select に変更しました。そして、その一時テーブルに対して関数を実行しました。実行時間は 3 ~ 4 秒に短縮されました。私を正しい道に導いたのは彼の明確な指摘だったので、私はこの質問を認めるために信用を与える必要があると思います. でもみんなありがとう。

4

3 に答える 3

1

UserIDがテーブルの主キーである場合、ユーザーが入力した質問に対してUser1 つ行う必要はありません。1 つSELECTだけでラップできますSELECT

SELECT @weight = @weight + COUNT(HoehnYarhID) + COUNT(DateOfBirth) + COUNT(GenderID) + COUNT(DateDiagnosed)
FROM dbo.[User] 
WHERE UserID = @userid 
于 2012-02-10T14:30:06.363 に答える
1

DISTINCT は、集計を行うため、絶対にパフォーマンス ヒットを引き起こします。本当に必要ですか?多くの場合、DISTINCT が表示される場合は、構造が独自に排除する必要がある重複を排除する機能によって、データまたは構造の問題が処理されていることを示しています。

その後、SELECT リスト内の相関クエリの代わりに、それを JOIN として移動するようにします。確実に成功するわけではありませんが、多くの場合、オプティマイザーはそれを計画にうまく組み込むことができます。

あなたが提示しているものの複雑さに基づいて、実行計画も検討します。最初に確認することは、完全に最適化されているか、それともタイムアウトになっているかです。タイムアウトした場合は、完全に計算された「十分な」計画ではなく、最善の推測を扱っています。その場合は、このクエリを単純化することを検討する必要があります。十分な計画がある場合は、その中でボトルネックがどこにあるかを確認します。

于 2012-02-10T14:44:44.183 に答える
0

スカラー値関数をインラインテーブル値関数に変換します。

于 2012-02-10T14:33:04.843 に答える