повышение производительности запроса на выборку для большой таблицы - PullRequest
0 голосов
/ 06 июня 2019

У меня большая таблица, и я использую SQL Server 2017. Таблица содержит 4 столбца, показанных ниже.

 Column name     Data type
 IndexDate       date
 Code            nvarchar(20)
 Sedol           nvarchar(7)
 Wgt             float

Таблица содержит дневные данные для различных индексов фондового рынка (например, S & P 500, Russell 1000, FTSE 100 и т. Д.) И вес каждой акции в индексе. Поэтому обычно ежедневно в базу данных добавляется около 16 000 строк данных.

Данные начинаются как раз перед 2000 годом. В настоящее время насчитывается около 60 миллионов строк.

В последнее время люди хотели запросить таблицу и имеют структуру, подобную приведенной ниже,

    Sedol     06-03-2019    06-04-2019   06-05-2019 ...
    ABC       0.03          0.0301       0.031
    MNB       0.015         0.0147       0.0145
    LPK       0.02          0.0201       0.0201

Итак, я создал динамическую хранимую процедуру, которая использует функцию pivot. Который выглядит ниже. Требуется три параметра: 2 даты для диапазона дат и еще один для кода индекса.

 declare @dates nvarchar(max) = ''

select @dates = @dates + QUOTENAME(date) + ',' 
    from DVLP_QES_MS.dbo.DateDimension where date >= @dateFrom and date <= @dateTo and IsWeekend = 0
set @dates = SUBSTRING(@dates, 1, len(@dates) - 1)

declare @q nvarchar(max) = ''


 set @q = 'select * from
(
    select Sedol, wgt, w.Date 
    from tblBMWeights w right join tblDates d on w.Date = d.Date
    where Code = ''' + @bm + ''' and d.IsWeekend = 0 and d.Date >= ''' + convert(varchar(10), @dateFrom, 110) + ''' and d.Date <= ''' + convert(varchar(10), @dateTo, 110) + '''
)source pivot(max(wgt) for Date in (' + @dates + ' )) as pvt order by Sedol'

exec(@q)

Обычно это работает, запрос данных за 6 месяцев занимает около 2 секунд. Однако в настоящее время существует потребность в дальнейшем запросе данных.

18 месяцев занимает около 14 секунд 30 месяцев занимает около 40 секунд 3 года занимает около 1 минуты

Я создал индексы для своих таблиц, чтобы повысить эффективность запросов. Мой вопрос заключается в том, как структурировать мою таблицу и как я могу улучшить производительность, чтобы данные за 3 года не запрашивали 1 минуту? Очевидно, что у других людей гораздо большие таблицы. Как им удается справляться с таблицами, в которых более 100 миллионов строк? Должен ли я иметь несколько таблиц?

Я сохранил план выполнения, но не могу прикрепить его к этому сообщению.

Обновление

Это ссылка на мой план

Три индекса

1)

 NONCLUSTERED INDEX [IDX_tblBenchmarkWeights_CodeDate_Sedol] ON [dbo]. 
 [tblBenchmarkWeights]
 (
    [Code] ASC,
    [Date] ASC
 )
 INCLUDE (  [Sedol]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO

2)

  NONCLUSTERED INDEX [IDX_tblBenchmarkWeights_CodeDateSedolWgt] ON [dbo]. 
 [tblBenchmarkWeights]
  (
     [Code] ASC,
     [Date] ASC
  )
  INCLUDE (     [Sedol],[Wgt]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO

3)

 NONCLUSTERED INDEX [IDX_tblBenchmarkWeights_DateSedol] ON [dbo]. 
 [tblBenchmarkWeights]
 (
    [Date] ASC
 )
  INCLUDE (     [Sedol]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO

Последний индекс в моей таблице дат

  NONCLUSTERED INDEX [IDX_DateDimension_IsWeekendDate] ON [dbo].[DateDimension]
 (
    [IsWeekend] ASC,
    [Date] ASC
  )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO

1 Ответ

0 голосов
/ 07 июня 2019

Чтобы повысить производительность запросов на выбор, следуйте приведенным ниже ограничениям:

Выбирайте только те поля, которые вам нужны, Создавайте индексы для быстрого поиска по таблице вместо того, чтобы полагаться на сканирование таблицы, Используйте EXISTS вместо INчтобы проверить наличие данных, используйте подсказку таблицы WITH (NOLOCK) в Select и Joins при запросе данных из любой таблицы, чтобы избежать взаимоблокировки, используйте try catch, чтобы избежать условия взаимоблокировки, используйте соответствующий тип данных в полях столбца, используйте имя схемы передИмя объекта SQL, используйте транзакцию в запросе

...