我们有一个表格,通过日期字段划分为不同的年份。
所有这些表都有一个视图(Call)
架构如下:
CREATE TABLE [dbo].[Call_2015](
[calID] [uniqueidentifier] NOT NULL,
[calPackageID] [int] NULL,
[calClientID] [int] NULL,
[calStartDate] [datetime] NOT NULL,
[calEndDate] [datetime] NOT NULL,
[calTimeIn] [char](5) NULL,
[calTimeOut] [char](5) NULL,
[calMinutes] [smallint] NULL,
[calPreferredTimeIn] [char](5) NULL,
[calPreferredTimeOut] [char](5) NULL,
[calActualTimeIn] [char](5) NULL,
[calActualTimeOut] [char](5) NULL,
[calActualMinutes] [smallint] NULL,
[calConfirmed] [smallint] NULL,
[calCarerID] [int] NULL,
[calRepCarerID] [int] NULL,
[calOriginalCarerID] [int] NULL,
[calContractID] [int] NULL,
[calNeedID] [int] NULL,
[calMedicationID] [int] NULL,
[calFrequency] [smallint] NULL,
[calFromDate] [datetime] NULL,
[calWeekNo] [smallint] NULL,
[calAlert] [smallint] NULL,
[calNoLeave] [smallint] NULL,
[calTimeCritical] [smallint] NULL,
[calStatus] [smallint] NULL,
[calClientAwayReasonID] [int] NULL,
[calCarerAwayReasonID] [int] NULL,
[calOutsideShift] [smallint] NULL,
[calHistoryID] [int] NULL,
[calInvoiceID] [int] NULL,
[calWagesheetID] [int] NULL,
[calReasonID] [int] NULL,
[calCallConfirmID] [varchar](50) NULL,
[calCreated] [datetime] NULL,
[calUpdated] [datetime] NULL,
[calVariation] [int] NULL,
[calVariationUserID] [int] NULL,
[calException] [smallint] NULL,
[calRetained] [smallint] NULL,
[calDoubleUpID] [uniqueidentifier] NULL,
[calDoubleUpOrder] [smallint] NULL,
[calNeedCount] [smallint] NULL,
[calNoStay] [smallint] NULL,
[calCoverCarerID] [int] NULL,
[calPayAdjustment] [real] NULL,
[calChargeAdjustment] [real] NULL,
[calTeamID] [int] NULL,
[calExpenses] [money] NULL,
[calMileage] [real] NULL,
[calOverrideStatus] [smallint] NULL,
[calLocked] [smallint] NULL,
[calDriver] [smallint] NULL,
[calPostcode] [char](10) NULL,
[calDayCentreID] [int] NULL,
[calMustHaveCarer] [smallint] NULL,
[calRoleID] [int] NULL,
[calUnavailableCarerID] [int] NULL,
[calClientInformed] [smallint] NULL,
[calFamilyInformed] [smallint] NULL,
[calMonthlyDay] [smallint] NULL,
[calOriginalTimeIn] [char](5) NULL,
[calLeadCarer] [smallint] NULL,
[calCallTypeID] [int] NULL,
[calActualStartDate] [datetime] NULL,
[calActualEndDate] [datetime] NULL,
[Table_Year] [int] NOT NULL,
CONSTRAINT [PK_Call_2015] PRIMARY KEY CLUSTERED
(
[Table_Year] ASC,
[calID] ASC,
[calStartDate] ASC,
[calEndDate] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Call_2015] WITH CHECK ADD CONSTRAINT [CK_Call_Year_2015] CHECK (([Table_Year]=(2015)))
GO
ALTER TABLE [dbo].[Call_2015] CHECK CONSTRAINT [CK_Call_Year_2015]
GO
ALTER TABLE [dbo].[Call_2015] WITH CHECK ADD CONSTRAINT [CK_calStartDate_2015] CHECK (([calStartDate]>=CONVERT([datetime],'01 Jan 2015 00:00:00',(0)) AND [calStartDate]<=CONVERT([datetime],'31 DEC 2015 23:59:59',(0))))
GO
ALTER TABLE [dbo].[Call_2015] CHECK CONSTRAINT [CK_calStartDate_2015]
GO
ALTER TABLE [dbo].[Call_2015] ADD CONSTRAINT [DF_Call_2015_Table_Year] DEFAULT ((2015)) FOR [Table_Year]
GO
表格的更新如下:
UPDATE Call SET
calStartDate = CASE
WHEN calFrequency = 14 THEN dbo.funDate(@MonthlyDay, MONTH(calStartDate), YEAR(calStartDate))
WHEN calFrequency IN (15,16) THEN dbo.funMonthlyCallDate(calFrequency, @MonthlyDay, calStartDate)
ELSE DateAdd(d, @StartDay-1, (calStartDate - datepart(dw,calStartDate)+1))
END,
calEndDate = CASE
WHEN calFrequency = 14 THEN dbo.funDate(@MonthlyDay + @EndDay - @StartDay, MONTH(calStartDate), YEAR(calStartDate))
WHEN calFrequency IN (15,16) THEN DATEADD(D, @EndDay - @StartDay, dbo.funMonthlyCallDate(calFrequency, @MonthlyDay, calStartDate))
ELSE DateAdd(d, @StartDay-1+@DayCount, (calStartDate - datepart(dw,calStartDate)+1))
END,
calTimeIn = @TimeIn,
calTimeOut = @TimeOut,
calMinutes = @Minutes,
calMonthlyDay = @MonthlyDay,
calClientInformed = Null,
calFamilyInformed = Null
WHERE calPackageID = @PackageID
AND calClientID = @ClientID
AND calWeekNo = @WeekNo
AND (DatePart(dw, calStartDate) = @OriginalDay OR calFrequency IN (14,15,16))
AND calStartDate BETWEEN @StartDate AND @EndDate
AND (calInvoiceID = 0 OR calInvoiceID Is Null OR @InvoicesFinalised = 1)
AND (calWagesheetID = 0 OR calWagesheetID Is Null OR @WagesFinalised = 1)
AND (calLocked = 0 OR calLocked Is Null)
AND (Table_Year = YEAR(@StartDate)
OR Table_Year =YEAR(@EndDate))
SP将一批依赖于输入的行更新到@StartDate和@EndDate(用两者之间的calStartDate更新所有行)
问题在于执行计划。操作有巨大的IO成本,我已经将其解决了SQL如何处理更新。
目前我们有20个这样的表;每年分区。每次更新都会导致更新每个表的索引,无论更新操作是否实际触及了表。
在本节下面,它继续以完全相同的方式更新视图中的每个表。
我不明白为什么会这样,因为我在查询文本中指定了Table_Year(表是分区的)。 SQL不应只更新必要的表吗?