我没有找到任何合适的方式来显示图像以外的查询计划,所以我添加了图像。在图像中我得到了执行计划,我想减少fullouter加入成本
,如果有人建议我降低成本的方式,那将是伟大的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
基于表名(dim *和fact *),我假设您正在对数据仓库模式进行排序报告。假设情况属实,那么您可以做的最好的事情就是考虑使用Columnstore索引(以及启用Columnstores后隐式的批处理模式执行)。这些索引经过大量压缩,通常可以显着提高IO绑定工作负载的性能。事实表是通常的候选者,因为它们是最大的/通常不适合缓冲池。
SQL 2016以后的所有版本都支持Columnstores,并且在Enterprise Edition中更快(更多并行性,内部更快的操作,如使用SIMD指令等)。请注意,它们不直接支持主键,因此这可能会影响您如何布置表格。您可以创建密钥(在内部作为b树二级索引),因此如果使用主键,则会节省一些空间。通常,事实表+列存储也使用分区来获得没有二级索引的另一层过滤。
请考虑使用columnstores替换事实表(可能在数据库的副本上进行实验)再次尝试查询。当您查看结果的查询计划时,我建议您还查看运算符是否以批处理模式运行。批处理模式运算符与行模式运算符不同。批处理模式针对现代CPU的体系结构进行了优化,以最大限度地减少进出CPU的内存流量。作为一个粗略的经验法则,柱存储+批处理模式可以实现10x-100x的差异。
可以帮助你的唯一过滤器是'dim_date.dimDateId> = X'这里有一个连接到cte和cte字段由3个表外连接组成。为了获得最佳性能,我会选择告诉sql一步一步做什么,否则使用最佳计划执行是非常危险的:
通过这种方式,您可以确保在最简单的步骤中直接过滤所需的内容,然后复杂的查询将在预设的行数下工作,从而保证性能非常好,而在几行上应用的非常糟糕的计划实际上并不重要。
较少细节:注意'INNER JOIN dim_status' - 如果没有FK约束,基数估计器可能会错过估计的返回行,因为无法理解表之间的关系。
我也可以看到优化尝试,因为过滤器已经向上升入cte。这与我提出的较小限制的计划类似。使用我的计划将强制行搜索到核心根源。