簡體   English   中英

清理由實體框架生成的大型SQL查詢

[英]Cleaning a big sql query generated by the Entity Framework

我正在檢查我的SQL查詢以查看是否可以對其進行優化,然后發現了一個龐大的查詢,其中僅包含很少的邏輯。

我了解查詢的某些部分,但不確定為什么每次都會選擇這么多列。

為什么實體框架這么多地分配/選擇網站實體? (網站實體包含諸如ID,標題,描述之類的列)。

 FROM      (SELECT 
                    [Project4].[Id] AS [Id], 
                    [Project4].[Title] AS [Title], 
                    [Project4].[Description] AS [Description], 
                    [Project4].[Url] AS [Url], 
                    [Project4].[BannerURL] AS [BannerURL], 
                    [Project4].[UserID] AS [UserID], 
                    [Project4].[CategoryID] AS [CategoryID], 
                    [Project4].[Keywords] AS [Keywords], 
                    [Project4].[Enabled] AS [Enabled], 
                    [Project4].[DateAdded] AS [DateAdded], 
                    [Project4].[Sponsored] AS [Sponsored], 
                    [Project4].[ServerIP] AS [ServerIP], 
                    [Project4].[ServerPort] AS [ServerPort], 
                    [Project4].[MonitorCheckedDate] AS [MonitorCheckedDate], 
                    [Project4].[IsOnline] AS [IsOnline], 
                    [Project4].[BannerFileName] AS [BannerFileName], 
                    [Project4].[Thumbnail] AS [Thumbnail], 
                    [Project4].[C1] AS [C1], 
                    [Project4].[C2] AS [C2], 

完整的SQL查詢:

SELECT TOP (25) 
    [Filter8].[Id1] AS [Id], 
    [Filter8].[Title] AS [Title], 
    [Filter8].[Description] AS [Description], 
    [Filter8].[Url] AS [Url], 
    [Filter8].[BannerURL] AS [BannerURL], 
    [Filter8].[UserID] AS [UserID], 
    [Filter8].[CategoryID] AS [CategoryID], 
    [Filter8].[Keywords] AS [Keywords], 
    [Filter8].[Enabled] AS [Enabled], 
    [Filter8].[DateAdded] AS [DateAdded], 
    [Filter8].[Sponsored] AS [Sponsored], 
    [Filter8].[ServerIP] AS [ServerIP], 
    [Filter8].[ServerPort] AS [ServerPort], 
    [Filter8].[MonitorCheckedDate] AS [MonitorCheckedDate], 
    [Filter8].[IsOnline] AS [IsOnline], 
    [Filter8].[BannerFileName] AS [BannerFileName], 
    [Filter8].[Thumbnail] AS [Thumbnail]

    // What's going on here?

    FROM ( SELECT [Filter7].[Id1], [Filter7].[Title], [Filter7].[Description], [Filter7].[Url], [Filter7].[BannerURL], [Filter7].[UserID], [Filter7].[CategoryID], [Filter7].[Keywords], [Filter7].[Enabled], [Filter7].[DateAdded], [Filter7].[Sponsored], [Filter7].[ServerIP], [Filter7].[ServerPort], [Filter7].[MonitorCheckedDate], [Filter7].[IsOnline], [Filter7].[BannerFileName], [Filter7].[Thumbnail], [Filter7].[C1], [Filter7].[C2], [Filter7].[C3], [Filter7].[IsAdminVerified1], [Filter7].[IsEmailVerified1], [Filter7].[BannedEndDate1], [Filter7].[BannedEndDate2], row_number() OVER (ORDER BY [Filter7].[Sponsored] DESC, [Filter7].[C2] DESC, [Filter7].[C3] DESC, [Filter7].[C1] DESC, [Filter7].[DateAdded] DESC) AS [row_number]
        FROM ( SELECT [Filter6].[Id1], [Filter6].[Title], [Filter6].[Description], [Filter6].[Url], [Filter6].[BannerURL], [Filter6].[UserID], [Filter6].[CategoryID], [Filter6].[Keywords], [Filter6].[Enabled], [Filter6].[DateAdded], [Filter6].[Sponsored], [Filter6].[ServerIP], [Filter6].[ServerPort], [Filter6].[MonitorCheckedDate], [Filter6].[IsOnline], [Filter6].[BannerFileName], [Filter6].[Thumbnail], [Filter6].[C1], [Filter6].[C2], [Filter6].[C3], [Filter6].[IsAdminVerified1], [Filter6].[IsEmailVerified1], [Filter6].[BannedEndDate1], [Filter6].[BannedEndDate2]
            FROM ( SELECT [Filter5].[Id1], [Filter5].[Title], [Filter5].[Description], [Filter5].[Url], [Filter5].[BannerURL], [Filter5].[UserID], [Filter5].[CategoryID], [Filter5].[Keywords], [Filter5].[Enabled], [Filter5].[DateAdded], [Filter5].[Sponsored], [Filter5].[ServerIP], [Filter5].[ServerPort], [Filter5].[MonitorCheckedDate], [Filter5].[IsOnline], [Filter5].[BannerFileName], [Filter5].[Thumbnail], [Filter5].[C1], [Filter5].[C2], [Filter5].[C3], [Filter5].[IsAdminVerified1], [Filter5].[IsEmailVerified1], [Filter5].[BannedEndDate1], [Filter5].[BannedEndDate2]
                FROM ( SELECT [Project5].[Id] AS [Id1], [Project5].[Title] AS [Title], [Project5].[Description] AS [Description], [Project5].[Url] AS [Url], [Project5].[BannerURL] AS [BannerURL], [Project5].[UserID] AS [UserID], [Project5].[CategoryID] AS [CategoryID], [Project5].[Keywords] AS [Keywords], [Project5].[Enabled] AS [Enabled], [Project5].[DateAdded] AS [DateAdded], [Project5].[Sponsored] AS [Sponsored], [Project5].[ServerIP] AS [ServerIP], [Project5].[ServerPort] AS [ServerPort], [Project5].[MonitorCheckedDate] AS [MonitorCheckedDate], [Project5].[IsOnline] AS [IsOnline], [Project5].[BannerFileName] AS [BannerFileName], [Project5].[Thumbnail] AS [Thumbnail], [Project5].[C1] AS [C1], [Project5].[C2] AS [C2], [Project5].[C3] AS [C3], [Extent6].[IsAdminVerified] AS [IsAdminVerified1], [Extent7].[IsEmailVerified] AS [IsEmailVerified1], [Extent8].[BannedEndDate] AS [BannedEndDate1], [Extent9].[BannedEndDate] AS [BannedEndDate2]

                    // Why the repeat?

                    FROM      (SELECT 
                        [Project4].[Id] AS [Id], 
                        [Project4].[Title] AS [Title], 
                        [Project4].[Description] AS [Description], 
                        [Project4].[Url] AS [Url], 
                        [Project4].[BannerURL] AS [BannerURL], 
                        [Project4].[UserID] AS [UserID], 
                        [Project4].[CategoryID] AS [CategoryID], 
                        [Project4].[Keywords] AS [Keywords], 
                        [Project4].[Enabled] AS [Enabled], 
                        [Project4].[DateAdded] AS [DateAdded], 
                        [Project4].[Sponsored] AS [Sponsored], 
                        [Project4].[ServerIP] AS [ServerIP], 
                        [Project4].[ServerPort] AS [ServerPort], 
                        [Project4].[MonitorCheckedDate] AS [MonitorCheckedDate], 
                        [Project4].[IsOnline] AS [IsOnline], 
                        [Project4].[BannerFileName] AS [BannerFileName], 
                        [Project4].[Thumbnail] AS [Thumbnail], 
                        [Project4].[C1] AS [C1], 
                        [Project4].[C2] AS [C2], 
                        (SELECT 
                            COUNT(1) AS [A1]
                            FROM [dbo].[WebsiteOut] AS [Extent5]
                            WHERE ([Project4].[Id] = [Extent5].[WebsiteID]) AND ([Extent5].[Unique] = 1)) AS [C3]
                        FROM ( SELECT 
                            [Project2].[Id] AS [Id], 
                            [Project2].[Title] AS [Title], 
                            [Project2].[Description] AS [Description], 
                            [Project2].[Url] AS [Url], 
                            [Project2].[BannerURL] AS [BannerURL], 
                            [Project2].[UserID] AS [UserID], 
                            [Project2].[CategoryID] AS [CategoryID], 
                            [Project2].[Keywords] AS [Keywords], 
                            [Project2].[Enabled] AS [Enabled], 
                            [Project2].[DateAdded] AS [DateAdded], 
                            [Project2].[Sponsored] AS [Sponsored], 
                            [Project2].[ServerIP] AS [ServerIP], 
                            [Project2].[ServerPort] AS [ServerPort], 
                            [Project2].[MonitorCheckedDate] AS [MonitorCheckedDate], 
                            [Project2].[IsOnline] AS [IsOnline], 
                            [Project2].[BannerFileName] AS [BannerFileName], 
                            [Project2].[Thumbnail] AS [Thumbnail], 
                            CASE WHEN ( EXISTS (SELECT 
                                1 AS [C1]
                                FROM [dbo].[WebsiteRating] AS [Extent4]
                                WHERE [Project2].[Id] = [Extent4].[WebsiteID]
                            )) THEN  CAST( [Project2].[C2] AS int) ELSE 5 END AS [C1], 
                            [Project2].[C1] AS [C2]
                            FROM ( SELECT 
                                [Project1].[Id] AS [Id], 
                                [Project1].[Title] AS [Title], 
                                [Project1].[Description] AS [Description], 
                                [Project1].[Url] AS [Url], 
                                [Project1].[BannerURL] AS [BannerURL], 
                                [Project1].[UserID] AS [UserID], 
                                [Project1].[CategoryID] AS [CategoryID], 
                                [Project1].[Keywords] AS [Keywords], 
                                [Project1].[Enabled] AS [Enabled], 
                                [Project1].[DateAdded] AS [DateAdded], 
                                [Project1].[Sponsored] AS [Sponsored], 
                                [Project1].[ServerIP] AS [ServerIP], 
                                [Project1].[ServerPort] AS [ServerPort], 
                                [Project1].[MonitorCheckedDate] AS [MonitorCheckedDate], 
                                [Project1].[IsOnline] AS [IsOnline], 
                                [Project1].[BannerFileName] AS [BannerFileName], 
                                [Project1].[Thumbnail] AS [Thumbnail], 
                                [Project1].[C1] AS [C1], 
                                (SELECT 
                                    AVG( CAST( [Extent3].[Rating] AS float)) AS [A1]
                                    FROM [dbo].[WebsiteRating] AS [Extent3]
                                    WHERE [Project1].[Id] = [Extent3].[WebsiteID]) AS [C2]
                                FROM ( SELECT 
                                    [Extent1].[Id] AS [Id], 
                                    [Extent1].[Title] AS [Title], 
                                    [Extent1].[Description] AS [Description], 
                                    [Extent1].[Url] AS [Url], 
                                    [Extent1].[BannerURL] AS [BannerURL], 
                                    [Extent1].[UserID] AS [UserID], 
                                    [Extent1].[CategoryID] AS [CategoryID], 
                                    [Extent1].[Keywords] AS [Keywords], 
                                    [Extent1].[Enabled] AS [Enabled], 
                                    [Extent1].[DateAdded] AS [DateAdded], 
                                    [Extent1].[Sponsored] AS [Sponsored], 
                                    [Extent1].[ServerIP] AS [ServerIP], 
                                    [Extent1].[ServerPort] AS [ServerPort], 
                                    [Extent1].[MonitorCheckedDate] AS [MonitorCheckedDate], 
                                    [Extent1].[IsOnline] AS [IsOnline], 
                                    [Extent1].[BannerFileName] AS [BannerFileName], 
                                    [Extent1].[Thumbnail] AS [Thumbnail], 
                                    (SELECT 
                                        COUNT(1) AS [A1]
                                        FROM [dbo].[WebsiteIn] AS [Extent2]
                                        WHERE ([Extent1].[Id] = [Extent2].[WebsiteID]) AND ([Extent2].[Unique] = 1)) AS [C1]
                                    FROM [dbo].[Websites] AS [Extent1]
                                )  AS [Project1]
                            )  AS [Project2]
                        )  AS [Project4] ) AS [Project5]
                    INNER JOIN [dbo].[Users] AS [Extent6] ON [Project5].[UserID] = [Extent6].[Id]
                    INNER JOIN [dbo].[Users] AS [Extent7] ON [Project5].[UserID] = [Extent7].[Id]
                    LEFT OUTER JOIN [dbo].[Users] AS [Extent8] ON [Project5].[UserID] = [Extent8].[Id]
                    LEFT OUTER JOIN [dbo].[Users] AS [Extent9] ON [Project5].[UserID] = [Extent9].[Id]
                    WHERE [Project5].[Enabled] = 1
                )  AS [Filter5]
                WHERE [Filter5].[IsAdminVerified1] = 1
            )  AS [Filter6]
            WHERE [Filter6].[IsEmailVerified1] = 1
        )  AS [Filter7]
        WHERE ([Filter7].[BannedEndDate1] IS NULL) OR ( CAST( SysDateTime() AS datetime2) > [Filter7].[BannedEndDate2])
    )  AS [Filter8]
    WHERE [Filter8].[row_number] > 0
    ORDER BY [Filter8].[Sponsored] DESC, [Filter8].[C2] DESC, [Filter8].[C3] DESC, [Filter8].[C1] DESC, [Filter8].[DateAdded] DESC

Linq:

(from website in _unitOfWorkRepository.WebsitesRepository.GetAll()
               let amountVotes = website.WebsiteIn.Count(x => x.Unique)
               let ratings = website.WebsiteRating.Select(x => x.Rating)
               let avgRate = ratings.Any() ? (int)ratings.Average() : 5
               let amountRedirects = website.WebsiteOut.Count(x => x.Unique)
               where
                   website.Enabled && website.Users.IsAdminVerified && website.Users.IsEmailVerified &&
                   (website.Users.BannedEndDate == null || DateTime.Now > website.Users.BannedEndDate)
               orderby website.Sponsored descending,
                   amountVotes descending,
                   amountRedirects descending,
                   avgRate descending,
                   website.DateAdded descending
               select website);

數據庫邏輯:

  • 用戶->(多個)網站-> WebsiteIn&WebsiteRating&WebsiteIn&WebsiteOut

我發現了一個龐大的查詢,只包含很少的邏輯。

完全沒有,它包含很多邏輯:

  • 4個let各自引起聚合子查詢的let語句。
  • 4個使用let語句結果的orderby子句

為了使SQL語句能夠按子查詢結果排序,應嵌套SELECT語句。 如果沒有嵌套,則需要在ORDER BY短語中重復聚合查詢。 因此,不管您相信與否,這已經是某種程度上經過優化的查詢形式。

為什么選擇這么多列

最終結果是完整的Website對象的列表,因此對應表中的所有列都應出現在結果集中。 這些列最終源自最內部的查詢。

因此,其中沒有太多可以輕松優化的方法,尤其是。 而不是查詢生成器。

如果查詢導致您遇到性能問題,則可以考慮

  1. 返回一個投影,即返回的列的子集(即:不是Website對象,而是屬性較少的類型)。
  2. 以包含總數的類型返回結果而不進行排序,並在內存中進行排序。 這將使查詢形狀變平,並從查詢優化器上花費一些精力。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM