推荐索引和查询改进

时间:2018-11-16 15:32:56

标签: sql performance tsql indexing sql-server-2014

我有这个跨服务器查询,可将大量行从日志数据库插入数据仓库。现在的问题是作业正在运行15个小时以上。需要大幅度减少这一点。需要有关此查询的最佳索引的建议,或者是否可以对查询本身进行任何改进。我在考虑URL的索引,fromDatabase的时间戳,toDatabase的ID时间戳。但是不能确定键列的最佳顺序,或者我是否应该使用include等,所以将不胜感激所有帮助。

  SELECT @SQL = N'
    INSERT INTO ' + @ToDatabase + '.dbo.Log
        (
        ImportDateTime
        ,ServerSource
        ,DatabaseSource
        ,Id
        ,Type
        ,UserName
        ,AppCode                        
        ,SubscriptionCode
        ,Duration
        ,ServiceNamespace
        ,ServiceName
        ,MethodName
        ,Parameters
        ,[Message]
        ,StackTrace
        ,Url
        ,UrlReferrer
        ,Browser
        ,BrowserVersion
        ,Platform
        ,Timestamp
        ,IpAddress
        ,EriAccountId
        )
        (
            SELECT
            ''' +  CONVERT(VARCHAR(50),@ImportDateTime) + '''
            ,''' +  @ServerSource + '''
            ,''' +  @DatabaseSource + '''
            ,Id
            ,Type
            ,UserName
            ,AppCode
            ,SubscriptionCode
            ,Duration
            ,ServiceNamespace
            ,ServiceName
            ,MethodName
            ,Parameters
            ,Message
            ,StackTrace
            ,Url
            ,UrlReferrer
            ,Browser
            ,BrowserVersion
            ,Platform
            ,Timestamp
            ,IpAddress
            ,EriAccountId

         FROM (
                select
                Id
                ,Type
                ,UserName
                ,AppCode
                ,SubscriptionCode
                ,Duration
                ,ServiceNamespace
                ,ServiceName
                ,MethodName
                ,Parameters
                ,Message
                ,StackTrace
                ,Url
                ,UrlReferrer
                ,Browser
                ,BrowserVersion
                ,Platform
                ,Timestamp
                ,IpAddress
                ,EriAccountId

    from openquery([' + @ServerSource + '],
                    ''select 
                    Id
                    ,Type
                    ,UserName
                    ,AppCode
                    ,SubscriptionCode
                    ,Duration
                    ,ServiceNamespace
                    ,ServiceName
                    ,MethodName
                    ,[Parameters] = CONVERT(NVARCHAR(MAX),[Parameters])
                    ,[Message]
                    ,StackTrace
                    ,Url
                    ,UrlReferrer
                    ,Browser
                    ,BrowserVersion
                    ,Platform
                    ,Timestamp
                    ,IpAddress
                    ,EriAccountId           
                    FROM ' + @FromDatabase + '.dbo.[Log] WITH (NOLOCK)
                    WHERE URL LIKE ''''http://online%'''' AND CONVERT(DATETIME2, TimeStamp) > ''''' + CONVERT(NVARCHAR(50),@AssessorDeploymentTimestamp) + ''''' AND CONVERT(DATETIME2,TimeStamp) > ''''' +  CONVERT(NVARCHAR(50),@DateCollected) + ''''' '') o
                    WHERE NOT EXISTS 
                        (SELECT 1
                        FROM ' + @ToDatabase + '.dbo.Log b 
                        WHERE b.id = o.id
                        AND CONVERT(DATETIME2, b.TimeStamp) > ''' +  CONVERT(NVARCHAR(50),@DateCollected) + '''
                        AND b.ServerSource = ''' +  @ServerSource + '''
                        )

                ) a
        )'

1 个答案:

答案 0 :(得分:1)

首先,我要说的是,除了实施正确的索引策略外,还应该遵循一些技巧来优化查询执行时间。

  • 在内部SELECT和JOIN语句中避免使用函数。函数(即使已缓存)也应以尽可能少的记录量执行,并且通常在最外面的select中执行。
  • 尽可能避免子查询,请选择JOIN。
  • 尽可能避免在where语句中使用非数字字段,对INT字段的索引扫描比对VARCHAR的扫描要快得多。
  • 避免使用WITH(NOLOCK)提示,因为您还将读取未提交的数据。它不会使查询运行得更快,并且您将拥有潜在的脏数据集。

在尝试优化查询时,请记住查询“解释器”用于解析查询的操作顺序:

  1. 从和联接块
  2. 成群结队
  3. 在哪里
  4. 选择

因此,请尝试编写查询以减少此块中每个块按此顺序返回的数目或记录。

也就是说,必须根据所使用的查询创建一个INDEX,如果在包含执行计划的情况下测试查询执行,则可以找到有用的提示,而SSMS通常可以为您提供很多帮助。

在这种情况下,我将在 URL TimeStamp 字段中按该顺序添加索引

CREATE CLUSTERED INDEX idx_Log ON yourDatabase.dbo.[log] (URL, Timestamp)