Рекомендуемое улучшение индекса и запросов - PullRequest
0 голосов
/ 16 ноября 2018

У меня есть этот межсерверный запрос, который вставляет большое количество строк из нашей базы данных журналов в наше хранилище данных.Проблема в том, что сейчас работа выполняется более 15 часов.Нужно радикально уменьшить это.Нужен совет по наилучшему индексу для этого запроса или если какие-либо улучшения могут быть сделаны по самому запросу.Я думаю, индекс на URL, метка времени для fromDatabase и метка времени ID для toDatabase.Но не уверен, в каком порядке расположены ключевые столбцы, или я должен использовать включенные и т. Д. Вся помощь очень ценится.

  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 голосов
/ 20 ноября 2018

Прежде всего я хочу сказать, что вы должны следовать некоторым советам по оптимизации времени выполнения запроса, помимо реализации правильной стратегии индекса.

  • Избегайте функций во внутренних операторах SELECT и JOIN.Функции (даже если они кэшированы) должны выполняться для наименьшего возможного количества записей, и, как правило, это происходит во внешнем выборе.
  • По возможности избегайте подзапросов, вместо этого выбирайте 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)
...