• SQL 耗时优化


    Ø  简介

    在平常的开发中,我们经常会编写各种各样的 SQL 语句,比如:SQL 查询、存储过程、或者视图查询等。当我们编写的 SQL 语句比较复杂,或者表的数据量比较大,导致查询超时!这时,就要去分析我们的 SQL 语句,导致耗时较长的原因,从而优化我们的 SQL 语句。

    说明:本文仅为笔者所思、所想、所写,有用之处欢迎借鉴,不对之处欢迎指出。

     

    1.   内连接查询中,子查询(关联相同的两张表)使用 TOP 子句解决耗时

    1)   LINQ 语句

    var datas = (from t1 in DataContext.Orders

                    join t3 in DataContext.UserInfoes on t1.UserId equals t3.id

                    join t5 in DataContext.Customers on t3.CustomerId equals t5.Id

                    join t7 in (from t1 in DataContext.CateringCategorys

                                join t3 in DataContext.CateringCategorys on t1.CategoryId equals t3.ParentId

                                where t1.Level == 1

                                select new

                                {

                                    CategoryId1 = t1.CategoryId,

                                    CategoryId2 = t3.CategoryId

                                }) on t5.TradeType equals t7.CategoryId2

                    where 1 == 1

                    && (cityId == 0 || t1.CityId == strCityId)

                    && t1.OrderStatusId >= (int)OrderStates.Undelivered && t1.OrderStatusId < (int)OrderStates.Cancelled

                    && t1.PayStatusId != (int)OrderPayStates.Unpaid

                    && (t1.PayTime >= startDate && t1.PayTime < endDate)

                    select new

                    {

                        CategoryId = t7.CategoryId1,

                        OrderId = t1.Id,

                        t1.RealTotal,

                        t3.CustomerId

                    }).ToArray();

     

    2)   生成 SQLsp_executesql 转换后的同等 SQL 语句)

    SELECT

        [Filter2].[CategoryId1] AS [CategoryId],

        [Filter1].[Id1] AS [Id],

        [Filter1].[RealTotal] AS [RealTotal],

        [Filter1].[CustomerId] AS [CustomerId]

        FROM   (SELECT [Extent1].[Id] AS [Id1], [Extent1].[RealTotal] AS [RealTotal], [Extent1].[PayTime] AS [PayTime], [Extent1].[CityId] AS [CityId1], [Extent2].[CustomerId] AS [CustomerId], [Extent3].[TradeType] AS [TradeType]

            FROM   [dbo].[Orders] AS [Extent1]

            INNER JOIN [dbo].[UserInfo] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[id]

            INNER JOIN [dbo].[Customer] AS [Extent3] ON [Extent2].[CustomerId] = [Extent3].[Id]

            WHERE ([Extent1].[OrderStatusId] >= 2) AND ([Extent1].[OrderStatusId] < 10) AND (cast(1 as bigint) <> [Extent1].[PayStatusId]) ) AS [Filter1]

        INNER JOIN  (SELECT [Extent4].[CategoryId] AS [CategoryId1], [Extent5].[CategoryId] AS [CategoryId2]

            FROM  [dbo].[Crm_CateringCategory] AS [Extent4]

            INNER JOIN [dbo].[Crm_CateringCategory] AS [Extent5] ON [Extent4].[CategoryId] = [Extent5].[ParentId]

            WHERE 1 = [Extent4].[Level] ) AS [Filter2] ON [Filter1].[TradeType] = [Filter2].[CategoryId2]

    WHERE ((0 = 0) OR ([Filter1].[CityId1] = '0') OR (([Filter1].[CityId1] IS NULL) AND ('0' IS NULL))) AND ([Filter1].[PayTime] >= '2018-12-01 00:00:00') AND ([Filter1].[PayTime] < '2019-01-01 00:00:00')

     

    3)   执行结果

    执行以上语句,耗时为:00:01:43.853

     

    4)   SQL 分析

    1.   首先,我们创建了一个子查询([Filter1]),关联了三张表:OrdersUserInofo Customer,这没什么好说的,是一个正常查询。

    2.   另外,又关联了一个子查询([Filter2]),Crm_CateringCategory Crm_CateringCategory 关联(使用 CategoryId ParentId 关联),就是因为这个子查询,导致了较长的耗时!这是为什么呢,这里先打个问号?

    3.   然后,笔者开始各种猜测

    1)   这个子查询数量量大?NO,只有23记录。

    2)   在关联的第二个 Crm_CateringCategory 表上再派生一层,再关联外层 Crm_CateringCategory 表,并只输出所需字段?结果还是不行!

    3)   因为关联的是相同的表?对的,就是这个原因!因为,尝试创建与 CateringCategory 相同的另一张表 CateringCategory_1 去关联查询,耗时问题就解决了。

    4)   为什么呢,表上加 (NOLOCK) 关键字也不管用,原因不祥(如有博友们知道,欢迎指出)!

    4.   然后,笔者又尝试在这个子查询上加上 TOP 子句,结果执行耗时变为了 00:00:00.740,耗时问题同样解决了。因为开发中,不可能再去创建一张相同的一张表。(Linq 只需加上 Take() 方法即可)。

  • 相关阅读:
    JAVA窗口程序实例一
    内存容量出现异常的解决办法
    Android Studio 2.0使用指南
    Android 开机自启服务
    Android 图形总结
    今日课堂总结
    JSON
    GET方法和POST方法
    ajax的简单介绍
    网页-豌豆上的公主
  • 原文地址:https://www.cnblogs.com/abeam/p/10064847.html
Copyright © 2020-2023  润新知