提高大表上选择查询的性能

时间:2019-06-06 15:33:42

标签: sql sql-server sql-server-2017

我有一张大桌子,并且正在使用SQL Server2017。该表包含下面显示的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年之前开始。目前大约有6000万行。

最近人们想查询表并具有如下结构,

    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

因此,我创建了一个使用数据透视功能的动态存储过程。如下图所示。它包含三个参数,两个用于日期范围的日期,另一个用于索引代码。

 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分钟?显然其他人有更大的表,他们如何处理超过1亿行的表?我应该有多个桌子吗?

我已经保存了执行计划,但似乎无法将其附在这篇文章上。

更新

这是my plan

的链接

三个索引

1st)

 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

2nd)

  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

3rd)

 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 :(得分:-1)

  

要提高选择查询的性能,请遵循以下约束:

     

仅选择您需要的字段,   快速创建索引以快速查找表,而不是依赖表扫描,   使用EXISTS代替IN检查数据是否存在,   在查询任何表中的数据时,在“选择并连接”上使用WITH(NOLOCK)表提示,以避免死锁,   使用try catch块以避免死锁情况,   在列字段上使用适当的数据类型,   在SQL Objectname之前使用架构名称,   在查询中使用交易