1

全て、

約250000レコードのユーザーテーブルがあります。次のクエリがあります(SQLの初心者です)が、実行に非常に長い時間がかかります。実行プランを確認したところ、実行時間の60%が2種類になっています。

SELECT TOP 50
    Flows_Users.UserName,
    Flows_Users.UserID,
    Flows_Users.ImageName,
    Flows_Users.DisplayName,
    Flows_UserBios.bio,
    FlowsCount = (
        SELECT Count(1)
        FROM Flows_Flows
        WHERE UserID = Flows_Users.UserID
            AND Flows_Flows.Active = '1'
    ),
    BeatsCount = (
        SELECT Count(1)
        FROM Flows_Beats
        WHERE UserName_ID = Flows_Users.UserID
            AND Flows_Beats.Active = '1'
    ),
    FollowersCount = (
        SELECT Count(1)
        FROM Flows_Follow
        WHERE FOLLOWING = Flows_Users.UserID
    ),
    FollowingCount = (
        SELECT Count(1)
        FROM Flows_Follow
        WHERE FOLLOWER = Flows_Users.UserID
    ),
    ISNULL(SUM(Flows_Flows_Likes_Dislikes.[Like]), 0) AS Likes,
    ISNULL(SUM(Flows_Flows_Likes_Dislikes.Dislike), 0) AS DisLikes
FROM Flows_Users
LEFT JOIN Flows_Flows
    ON Flows_Users.UserID = Flows_Flows.UserID
LEFT JOIN Flows_UserBios
    ON Flows_Users.UserID = Flows_UserBios.userid
LEFT JOIN Flows_Flows_Likes_Dislikes
    ON Flows_Flows.FlowID = Flows_Flows_Likes_Dislikes.FlowID
WHERE Flows_Users.UserID = Flows_Users.UserID
GROUP BY Flows_Users.UserID,
    Flows_Users.UserName,
    Flows_Users.ImagePath,
    Flows_Users.ImageName,
    Flows_Users.DisplayName,
    Flows_UserBios.bio
ORDER BY
    [Likes] DESC,
    [Dislikes] ASC,
    FlowsCount DESC

私はこれが混乱していることを知っていますが、それはテーブルが数万に過ぎないときに仕事を成し遂げました。これをより速くする方法はありますか?現在、実行には最大5〜10分かかります。これもストアドプロシージャに含まれており、インデックスを作成する必要のある列があるように感じます。

4

3 に答える 3

1

@PreetSanghtが変更を推測したように

この部分

FlowsCount = (
    SELECT Count(1)
    FROM Flows_Flows
    WHERE UserID = Flows_Users.UserID
        AND Flows_Flows.Active = '1'
),
BeatsCount = (
    SELECT Count(1)
    FROM Flows_Beats
    WHERE UserName_ID = Flows_Users.UserID
        AND Flows_Beats.Active = '1'
),
FollowersCount = (
    SELECT Count(1)
    FROM Flows_Follow
    WHERE FOLLOWING = Flows_Users.UserID
),
FollowingCount = (
    SELECT Count(1)
    FROM Flows_Follow
    WHERE FOLLOWER = Flows_Users.UserID
),

このようなものに

sum(case when Flows_Flows.Active = '1' then 1 else 0 end) 
over (partition by UserID order by Flows_Flows.UserID) as FlowsCount,

sum(case when Flows_Beats.Active = '1' then 1 else 0 end) 
over (partition by UserName_ID order by Flows_Flows.UserID) as BeatsCount,

count(1) over(parition by FOLLOWING order by Flows_Flows.UserID) as FollowersCount,
count(1) over(parition by FOLLOWER order by Flows_Flows.UserID) as FollowingCount,


私はあなたがウィンドウ関数とover()句について読むべきだという考えに行くと思います

クエリ全体が必要な場合は、サンプルデータとテーブルスキーマを投稿してください

于 2013-01-19T09:31:02.410 に答える
0

他の提案を実装したら、クエリをストアド プロシージャに変換します。このように、サーバーはクエリが実行されるたびに実行計画を作成する必要はありません。

于 2013-01-19T09:24:16.603 に答える
0

私はそれらのテーブルを持っていないので、この変更を試してください。パッチを当てる必要があるかもしれません。検証後、実行計画を確認し、テーブル スキャンを探します。次にインデックスを追加します。数値インデックスが大きい場合は、含まれる列を検討してください。私は個人的にこれをストアド プロシージャではなくビューに変更しますが、それが私の好みです。

* を数えるほうが実際にはわずかに優れていると誰かが言ったことがありますが、それは SQL Server 2000 の時代であり、まだ関連があるかどうかはわかりません。

可能であれば、可能な場合は左結合を内部結合に変更します。すなわち。ユーザーは完全に削除されていないと想定しているため、ユーザー ID 結合を内部に変更し、必要に応じて無効なアカウントをフィルター処理します。

    SELECT TOP 50
    Flows_Users.UserName,
    Flows_Users.UserID,
    Flows_Users.ImageName,
    Flows_Users.DisplayName,
    Flows_UserBios.bio,
    a.FlowsCount,
    b.BeatsCount,
    c.FollowersCount,
    d.FollowingCount,
    ISNULL(SUM(Flows_Flows_Likes_Dislikes.[Like]), 0) AS Likes,
    ISNULL(SUM(Flows_Flows_Likes_Dislikes.Dislike), 0) AS DisLikes
FROM Flows_Users
LEFT JOIN     (    SELECT Count(*) FlowCount
        FROM Flows_Flows
        WHERE UserID = Flows_Users.UserID
            AND Flows_Flows.Active = '1') a
LEFT JOIN  (SELECT Count(*) as 
        FROM Flows_Beats
        WHERE UserName_ID = Flows_Users.UserID
            AND Flows_Beats.Active = '1') b
LEFT JOIN  (SELECT Count(*) as FollowersCount
        FROM Flows_Follow
        WHERE FOLLOWING = Flows_Users.UserID) c
LEFT JOIN  (
        SELECT Count(*) as FollowingCount
        FROM Flows_Follow
        WHERE FOLLOWER = Flows_Users.UserID) d
LEFT JOIN Flows_Flows
    ON Flows_Users.UserID = Flows_Flows.UserID
LEFT JOIN Flows_UserBios
    ON Flows_Users.UserID = Flows_UserBios.userid
LEFT JOIN Flows_Flows_Likes_Dislikes
    ON Flows_Flows.FlowID = Flows_Flows_Likes_Dislikes.FlowID
WHERE Flows_Users.UserID = Flows_Users.UserID
GROUP BY Flows_Users.UserID,
    Flows_Users.UserName,
    Flows_Users.ImagePath,
    Flows_Users.ImageName,
    Flows_Users.DisplayName,
    Flows_UserBios.bio
ORDER BY
    [Likes] DESC,
    [Dislikes] ASC,
    FlowsCount DESC
于 2013-01-19T09:18:41.597 に答える