Sql 这更疯狂。所有这些(a)临时工作表和(b)临时工作表业务的临时工作表都是非规范化数据库的典型症状。或者无法理解数据的原貌,无法获取数据,无法创建不必要的工作表来满足您的需要。我并不是想让你改变这一点,这将是的第一选择,这将消除对整个混乱局面的需要 第二个选
Sql 这更疯狂。所有这些(a)临时工作表和(b)临时工作表业务的临时工作表都是非规范化数据库的典型症状。或者无法理解数据的原貌,无法获取数据,无法创建不必要的工作表来满足您的需要。我并不是想让你改变这一点,这将是的第一选择,这将消除对整个混乱局面的需要 第二个选,sql,sql-server,performance,tsql,Sql,Sql Server,Performance,Tsql,这更疯狂。所有这些(a)临时工作表和(b)临时工作表业务的临时工作表都是非规范化数据库的典型症状。或者无法理解数据的原貌,无法获取数据,无法创建不必要的工作表来满足您的需要。我并不是想让你改变这一点,这将是的第一选择,这将消除对整个混乱局面的需要 第二个选项是,查看是否可以从原始表格生成最终结果: -不使用工作台 -使用一个工作台 而不是两个工作台(16500和413000“记录”;这是两个指数非规范化级别) 第三个选项是,改善你的混乱状况。。。但首先你需要了解表演猪在哪里 但是查询的性能相当差
这更疯狂。所有这些(a)临时工作表和(b)临时工作表业务的临时工作表都是非规范化数据库的典型症状。或者无法理解数据的原貌,无法获取数据,无法创建不必要的工作表来满足您的需要。我并不是想让你改变这一点,这将是的第一选择,这将消除对整个混乱局面的需要
第二个选项是,查看是否可以从原始表格生成最终结果:
-不使用工作台
-使用一个工作台
而不是两个工作台(16500和413000“记录”;这是两个指数非规范化级别)
第三个选项是,改善你的混乱状况。。。但首先你需要了解表演猪在哪里
但是查询的性能相当差,正如您可能期望的那样,有如此多的自连接
胡说八道、连接和自连接不需要任何成本。问题在于,成本在于:
您正在堆上操作
没有主键
- 仅这两项就意味着绩效未被考虑,也无法预期
在联接中使用运算符和函数(而不是纯“=”)意味着服务器无法对搜索值做出合理的决定,因此您一直在扫描表
表大小(在Dev/Test/Prod上可能不同)
有效、可用的索引(或否)
成本就在这四个项目上,堆在各个方面都非常缓慢,运营商也没有找到任何东西来缩小搜索范围;不是存在或不存在联接操作的事实
下一系列的问题就是你的做法
您是否意识到“连接”是具体化的表;您不是在“加入”您是在动态地实现表格???没有什么是免费的:物质化有巨大的成本。你是如此专注于物质化而不知道成本,以至于你认为连接是问题所在。为什么呢
在做出任何合理的编码决策之前,需要打开SHOWPLAN和STATISTICS IO。在开发时这样做(它还远没有准备好进行“测试”)。这会让你对桌子有个概念;连接(你所期望的与它所决定的,从混乱中);工作台(具体化)。CPU的高使用率不算什么,等你看到你的代码使用了疯狂的I/O后再说。如果你想争论在飞行中实现的成本,请便,但先发布展示计划
请注意,具体化的表没有索引,因此它每次都对um“联接”进行表扫描
“按原样选择”所做的工作比它需要的多出数十倍(可能数百倍)。既然桌子就在那里,而且它没有移动,那么将它的另一个版本具体化是一件非常愚蠢的事情。因此,真正的问题是:
.
如果您不确定,这意味着删除六个具体化的表,并将它们替换为与主表的纯联接
如果你能接受分手,那就这么做吧。创建并加载此查询将首先使用的临时表(这意味着只有3个临时表用于聚合)。确保在正确的列上放置索引
因此,可以用3个到主表的联接和3个到临时聚合表的联接来替换6个带的具体化表
沿着这条线的某个地方,你已经确定你有笛卡尔积和复制品;您没有解决问题的原因(开发生成所需集合的代码),而是避免了所有这一切,让它充满了重复,并删除了不同的行。这会导致额外的工作台。解决这个问题。在合理地预期使用它们的选择是正确的之前,您必须首先使每个临时表(工作表、具体化表等)正确
然后尝试选择
我想这都是在WebData中运行的。如果不是,则将IsGreaterThan()放在此数据库中
请提供UDF大于的DDL。如果这是使用表格,我们需要了解它
请在CREATETABLE语句中提供声称的索引。它们可能是不正确的或更糟的,折叠起来不需要
忘记身份或强制值,这个工作表堆的实际、真实、自然、逻辑PK是什么
确保联接列上没有数据类型不匹配
就我个人而言,我会羞于发布像你这样的代码。它是完全不可读取的。为了找出这里的问题,我所做的就是格式化它,使它可读。使代码可读是有原因的,例如,它允许您快速发现问题。你使用什么格式并不重要,但你必须格式化,而且你必须始终如一地这样做。请在再次发布之前将其清理干净,并附上所有相关DDL
难怪你一直没有得到答案。您需要先做一些基础工作(showplan等),并准备代码,以便人类能够阅读,从而提供答案。
SELECT
MIN(units.MaxAccommodationAvailabilityPax) AS MaxAccommodationAvailabilityPax,
MIN(units.MaxAccommodationAvailabilityAdults) AS MaxAccommodationAvailabilityAdults,
StartDate AS DepartureDate,
EndDate AS ReturnDate,
DATEDIFF(DAY, StartDate, EndDate) AS Duration,
MIN(units.accommodation_id) AS AccommodationID,
x.accommodation_unit_id AS AccommodationUnitID,
SUM(Price) AS Price,
MAX(num_pax) AS Occupancy,
SUM(offer_discount) AS OfferSaving,
MIN(date_correct) AS DateTimeCorrect,
MIN(rooms_remaining) AS RoomsRemaining,
MIN(CONVERT(int, dbo.IsGreaterThan(ISNULL(eta_available, 0)+ISNULL(nights_remaining_count, 0), 0)))
AS EtaAvailable
FROM single_date_availability fp INNER JOIN (
-- This gets max availability for the whole accommodation on the arrival date
SELECT accommodation_id, arrival_date,
CASE EtaAvailable
WHEN 1 THEN 99
ELSE MaxAccommodationAvailabilityPax
END AS MaxAccommodationAvailabilityPax,
CASE EtaAvailable
WHEN 1 THEN 99
ELSE MaxAccommodationAvailabilityAdults
END AS MaxAccommodationAvailabilityAdults
FROM (
SELECT accommodation_id, arrival_date,
SUM(MaximumOccupancy)
MaxAccommodationAvailabilityPax,
SUM(MaximumAdults) MaxAccommodationAvailabilityAdults,
CONVERT(int, WebData.dbo.IsGreaterThan(SUM(EtaAvailable), -1))
AS EtaAvailable
FROM (
SELECT accommodation_id,
arrival_date,
MIN(rooms_remaining*max_occupancy) as MaximumOccupancy,
MIN(rooms_remaining*max_adults) as MaximumAdults,
MIN(ISNULL(eta_available, 0) + ISNULL(nights_remaining_count, 0) - 1)
as EtaAvailable
FROM single_date_availability
GROUP BY accommodation_id, accommodation_unit_id, arrival_date
) a
GROUP BY accommodation_id, arrival_date
) b
) units
ON fp.accommodation_id = units.accommodation_id
AND fp.arrival_date = units.arrival_date INNER JOIN (
-- This gets every combination of StartDate and EndDate for each Unit/Occupancy
SELECT D.I.S.T.I.N.C.T a.accommodation_unit_id,
StartDate = a.arrival_date,
EndDate = b.arrival_date+1,
Duration = DATEDIFF(DAY, a.arrival_date, b.arrival_date)+1
FROM single_date_availability AS a INNER JOIN (
SELECT accommodation_unit_id,
arrival_date
FROM single_date_availability
) AS b
ON a.accommodation_unit_id = b.accommodation_unit_id
AND DATEDIFF(DAY, a.arrival_date, b.arrival_date)+1 >= a.min_stay_nights
AND DATEDIFF(DAY, a.arrival_date, b.arrival_date)+1 <= (
CASE a.max_stay_nights
WHEN 0 THEN 28
ELSE a.max_stay_nights
END
)
) x ON fp.accommodation_unit_id = x.accommodation_unit_id
AND fp.arrival_date >= x.StartDate
AND fp.arrival_date < x.EndDate
GROUP BY x.accommodation_unit_id, StartDate, EndDate
-- This ensures that all dates between StartDate and EndDate are actually available
HAVING COUNT(*) = DATEDIFF(DAY, StartDate, EndDate)
选择
最小值(单位:MaxAccountationAvailabilityPax)为MaxAccountationAvailabilityPax,
最小值(单位:MaxAccountationAvailabilityDults)为MaxAccountationAvailabilityDults,
起始日期为出发日期,
EndDate作为ReturnDate,
DATEDIFF(天、开始日期、结束日期)作为持续时间,
住宿id的最小值(单位住宿id),
x.住宿单位id作为住宿起始,
总和(价格)作为价格,
入住率最高(人数),
?
SELECT
MIN(units.MaxAccommodationAvailabilityPax) AS MaxAccommodationAvailabilityPax,
MIN(units.MaxAccommodationAvailabilityAdults) AS MaxAccommodationAvailabilityAdults,
StartDate AS DepartureDate,
EndDate AS ReturnDate,
DATEDIFF(DAY, StartDate, EndDate) AS Duration,
MIN(units.accommodation_id) AS AccommodationID,
x.accommodation_unit_id AS AccommodationUnitID,
SUM(Price) AS Price,
MAX(num_pax) AS Occupancy,
SUM(offer_discount) AS OfferSaving,
MIN(date_correct) AS DateTimeCorrect,
MIN(rooms_remaining) AS RoomsRemaining,
MIN(CONVERT(int, dbo.IsGreaterThan(ISNULL(eta_available, 0)+ISNULL(nights_remaining_count, 0), 0))) AS EtaAvailable
FROM single_date_availability fp
INNER JOIN (
/* This gets max availability for the whole accommodation on the arrival date */
SELECT accommodation_id, arrival_date,
CASE EtaAvailable WHEN 1 THEN 99 ELSE MaxAccommodationAvailabilityPax END AS MaxAccommodationAvailabilityPax,
CASE EtaAvailable WHEN 1 THEN 99 ELSE MaxAccommodationAvailabilityAdults END AS MaxAccommodationAvailabilityAdults
FROM (SELECT accommodation_id, arrival_date, SUM(MaximumOccupancy) MaxAccommodationAvailabilityPax, SUM(MaximumAdults) MaxAccommodationAvailabilityAdults,
CONVERT(int, WebData.dbo.IsGreaterThan(SUM(EtaAvailable), -1)) AS EtaAvailable
FROM (SELECT accommodation_id, arrival_date, MIN(rooms_remaining*max_occupancy) as MaximumOccupancy,
MIN(rooms_remaining*max_adults) as MaximumAdults, MIN(ISNULL(eta_available, 0) + ISNULL(nights_remaining_count, 0) - 1) as EtaAvailable
FROM single_date_availability
GROUP BY accommodation_id, accommodation_unit_id, arrival_date) a
GROUP BY accommodation_id, arrival_date) b
) units ON fp.accommodation_id = units.accommodation_id AND fp.arrival_date = units.arrival_date
INNER JOIN (
/* This gets every combination of StartDate and EndDate for each Unit/Occupancy */
SELECT DISTINCT a.accommodation_unit_id, StartDate = a.arrival_date,
EndDate = b.arrival_date+1, Duration = DATEDIFF(DAY, a.arrival_date, b.arrival_date)+1
FROM single_date_availability AS a
INNER JOIN (SELECT accommodation_unit_id, arrival_date FROM single_date_availability) AS b
ON a.accommodation_unit_id = b.accommodation_unit_id
AND DATEDIFF(DAY, a.arrival_date, b.arrival_date)+1 >= a.min_stay_nights
AND DATEDIFF(DAY, a.arrival_date, b.arrival_date)+1 <= (CASE a.max_stay_nights WHEN 0 THEN 28 ELSE a.max_stay_nights END)
) x ON fp.accommodation_unit_id = x.accommodation_unit_id AND fp.arrival_date >= x.StartDate AND fp.arrival_date < x.EndDate
GROUP BY x.accommodation_unit_id, StartDate, EndDate
/* This ensures that all dates between StartDate and EndDate are actually available */
HAVING COUNT(*) = DATEDIFF(DAY, StartDate, EndDate)
AND DATEDIFF(DAY , a.arrival_date , b.arrival_date) + 1 >= a.min_stay_nights
AND DATEDIFF(DAY , a.arrival_date , b.arrival_date) + 1 <= (CASE a.max_stay_nights WHEN 0 THEN 28 ELSE a.max_stay_nights END)
and a.min_stay_nights<=DATEDIFF(DAY , a.arrival_date , b.arrival_date)
and (CASE a.max_stay_nights WHEN 0 THEN 28 ELSE a.max_stay_nights END)>=DATEDIFF(DAY , a.arrival_date , b.arrival_date) + 1
SELECT
MIN(units.MaxAccommodationAvailabilityPax) AS MaxAccommodationAvailabilityPax,
MIN(units.MaxAccommodationAvailabilityAdults) AS MaxAccommodationAvailabilityAdults,
StartDate AS DepartureDate,
EndDate AS ReturnDate,
DATEDIFF(DAY, StartDate, EndDate) AS Duration,
MIN(units.accommodation_id) AS AccommodationID,
x.accommodation_unit_id AS AccommodationUnitID,
SUM(Price) AS Price,
MAX(num_pax) AS Occupancy,
SUM(offer_discount) AS OfferSaving,
MIN(date_correct) AS DateTimeCorrect,
MIN(rooms_remaining) AS RoomsRemaining,
MIN(CONVERT(int, dbo.IsGreaterThan(ISNULL(eta_available, 0)+ISNULL(nights_remaining_count, 0), 0)))
AS EtaAvailable
FROM single_date_availability fp INNER JOIN (
-- This gets max availability for the whole accommodation on the arrival date
SELECT accommodation_id, arrival_date,
CASE EtaAvailable
WHEN 1 THEN 99
ELSE MaxAccommodationAvailabilityPax
END AS MaxAccommodationAvailabilityPax,
CASE EtaAvailable
WHEN 1 THEN 99
ELSE MaxAccommodationAvailabilityAdults
END AS MaxAccommodationAvailabilityAdults
FROM (
SELECT accommodation_id, arrival_date,
SUM(MaximumOccupancy)
MaxAccommodationAvailabilityPax,
SUM(MaximumAdults) MaxAccommodationAvailabilityAdults,
CONVERT(int, WebData.dbo.IsGreaterThan(SUM(EtaAvailable), -1))
AS EtaAvailable
FROM (
SELECT accommodation_id,
arrival_date,
MIN(rooms_remaining*max_occupancy) as MaximumOccupancy,
MIN(rooms_remaining*max_adults) as MaximumAdults,
MIN(ISNULL(eta_available, 0) + ISNULL(nights_remaining_count, 0) - 1)
as EtaAvailable
FROM single_date_availability
GROUP BY accommodation_id, accommodation_unit_id, arrival_date
) a
GROUP BY accommodation_id, arrival_date
) b
) units
ON fp.accommodation_id = units.accommodation_id
AND fp.arrival_date = units.arrival_date INNER JOIN (
-- This gets every combination of StartDate and EndDate for each Unit/Occupancy
SELECT D.I.S.T.I.N.C.T a.accommodation_unit_id,
StartDate = a.arrival_date,
EndDate = b.arrival_date+1,
Duration = DATEDIFF(DAY, a.arrival_date, b.arrival_date)+1
FROM single_date_availability AS a INNER JOIN (
SELECT accommodation_unit_id,
arrival_date
FROM single_date_availability
) AS b
ON a.accommodation_unit_id = b.accommodation_unit_id
AND DATEDIFF(DAY, a.arrival_date, b.arrival_date)+1 >= a.min_stay_nights
AND DATEDIFF(DAY, a.arrival_date, b.arrival_date)+1 <= (
CASE a.max_stay_nights
WHEN 0 THEN 28
ELSE a.max_stay_nights
END
)
) x ON fp.accommodation_unit_id = x.accommodation_unit_id
AND fp.arrival_date >= x.StartDate
AND fp.arrival_date < x.EndDate
GROUP BY x.accommodation_unit_id, StartDate, EndDate
-- This ensures that all dates between StartDate and EndDate are actually available
HAVING COUNT(*) = DATEDIFF(DAY, StartDate, EndDate)