查询执行计划中的查询优化

问题描述 投票:4回答:2

我没有找到任何合适的方式来显示图像以外的查询计划,所以我添加了图像。在图像中我得到了执行计划,我想减少fullouter加入成本

enter image description here

,如果有人建议我降低成本的方式,那将是伟大的for better query plan link

WITH cte AS
(
SELECT
 coalesce(fact_connect_hours.dimProviderId,fact_connect_hour_hum_shifts.dimProviderId,fact_connect_hour_clock_times.dimProviderId)
  as dimProviderId,
  coalesce(fact_connect_hours.dimScribeId,fact_connect_hour_hum_shifts.dimScribeId,fact_connect_hour_clock_times.dimScribeId)
  as dimScribeId
 ,coalesce(fact_connect_hours.dimDateId,fact_connect_hour_hum_shifts.dimDateId,fact_connect_hour_clock_times.dimDateId)
  as dimDateId
,factConnectHourId
,totalProviderLogTime
,providerFirstJoinTime
,providerLastEndTime
,scribeFirstLogin
,scribeLastLogout
,totalScribeLogTime
, totalScopeTime
, totalStreamTime
, firstScopeJoinTime
, lastScopeEndTime
, scopeLastActivityTime
, firstStreamJoinTime
, lastStreamEndTime
, streamLastActivityTime

,fact_connect_hour_hum_shifts.shiftStartTime
,fact_connect_hour_hum_shifts.shiftEndTime
,fact_connect_hour_hum_shifts.totalShiftTime
,fact_connect_hour_clock_times.ClockStartTimestamp
,fact_connect_hour_clock_times.ClockEndTimestamp
,fact_connect_hour_clock_times.totalClockTime
,fact_connect_hour_hum_shifts.shiftTitle
,fact_connect_hours.dimStatusId
,dim_status.status
FROM fact_connect_hours
INNER JOIN  dim_status on fact_connect_hours.dimStatusId=dim_status.dimStatusId
  full outer JOIN fact_connect_hour_hum_shifts
 ON ( fact_connect_hour_hum_shifts.dimDateId=fact_connect_hours.dimDateId 
  and fact_connect_hour_hum_shifts.dimProviderId=fact_connect_hours.dimProviderId 
  and fact_connect_hour_hum_shifts.dimScribeId=fact_connect_hours.dimScribeId)
full outer join fact_connect_hour_clock_times
    on (fact_connect_hours.dimDateId = fact_connect_hour_clock_times.dimDateId 
        and fact_connect_hours.dimProviderId= fact_connect_hour_clock_times.dimProviderId 
        and fact_connect_hours.dimScribeId = fact_connect_hour_clock_times.dimScribeId
       )
WHERE coalesce(fact_connect_hours.dimDateId,fact_connect_hour_hum_shifts.dimDateId,fact_connect_hour_clock_times.dimDateId)>=732
) SELECT cte.*
  ,dim_date.tranDate
,dim_date.tranMonth
,dim_date.tranMonthName
,dim_date.tranYear
,dim_date.tranWeek
,dim_scribe.scribeUId
,dim_scribe.scribeFirstname
,dim_scribe.scribeFullname
,dim_scribe.scribeLastname
,dim_scribe.location
,dim_scribe.partner
,dim_scribe.beta
,dim_scribe.currentStatus
,dim_scribe.scribeEmail
,dim_scribe.augmedixEmail
,dim_scribe.partner
,dim_provider.scribeManager
,dim_provider.clinicalAccountManagerName
,dim_provider.providerUId
,dim_provider.beta
,dim_provider.accountName
,dim_provider.accountGroup
,dim_provider.accountType
,dim_provider.goLiveDate
,dim_provider.siteName
,dim_provider.churnDate
,dim_provider.providerFullname
,dim_provider.providerEmail

  from cte

   INNER JOIN   dim_date on cte.dimDateId=dim_date.dimDateId
   inner JOIN  aug_bi_dw.dbo.dim_provider AS dim_provider on cte.dimProviderId=dim_provider.dimProviderId 
   inner join aug_bi_dw.dbo.dim_scribe AS dim_scribe on cte.dimScribeId=dim_scribe.dimScribeId 

where dim_date.dimDateId>=732
sql sql-server tsql sql-server-2016
2个回答
2
投票

基于表名(dim *和fact *),我假设您正在对数据仓库模式进行排序报告。假设情况属实,那么您可以做的最好的事情就是考虑使用Columnstore索引(以及启用Columnstores后隐式的批处理模式执行)。这些索引经过大量压缩,通常可以显着提高IO绑定工作负载的性能。事实表是通常的候选者,因为它们是最大的/通常不适合缓冲池。

SQL 2016以后的所有版本都支持Columnstores,并且在Enterprise Edition中更快(更多并行性,内部更快的操作,如使用SIMD指令等)。请注意,它们不直接支持主键,因此这可能会影响您如何布置表格。您可以创建密钥(在内部作为b树二级索引),因此如果使用主键,则会节省一些空间。通常,事实表+列存储也使用分区来获得没有二级索引的另一层过滤。

请考虑使用columnstores替换事实表(可能在数据库的副本上进行实验)再次尝试查询。当您查看结果的查询计划时,我建议您还查看运算符是否以批处理模式运行。批处理模式运算符与行模式运算符不同。批处理模式针对现代CPU的体系结构进行了优化,以最大限度地减少进出CPU的内存流量。作为一个粗略的经验法则,柱存储+批处理模式可以实现10x-100x的差异。


0
投票

可以帮助你的唯一过滤器是'dim_date.dimDateId> = X'这里有一个连接到cte和cte字段由3个表外连接组成。为了获得最佳性能,我会选择告诉sql一步一步做什么,否则使用最佳计划执行是非常危险的:

  1. 使用过滤器在表fact_connect_hours,fact_connect_hour_hum_shifts和fact_connect_hour_clock_times中使用3个语句,并将结果(只需要主键或所有列)转换为3个临时值,如#fact_connect_hours,#fact_connect_hour_hum_shifts和#fact_connect_hour_clock_times
  2. 如果temps只有PK,请按原样使用该语句,但用temps替换或使用temps join real tables
  3. 将索引(如果不存在)添加到列fact_connect_hours.dimDateId,fact_connect_hour_hum_shifts.dimDateId和fact_connect_hour_clock_times.dimDateId

通过这种方式,您可以确保在最简单的步骤中直接过滤所需的内容,然后复杂的查询将在预设的行数下工作,从而保证性能非常好,而在几行上应用的非常糟糕的计划实际上并不重要。

较少细节:注意'INNER JOIN dim_status' - 如果没有FK约束,基数估计器可能会错过估计的返回行,因为无法理解表之间的关系。

我也可以看到优化尝试,因为过滤器已经向上升入cte。这与我提出的较小限制的计划类似。使用我的计划将强制行搜索到核心根源。

© www.soinside.com 2019 - 2024. All rights reserved.