问题
我们正试图了解为什么通过调用存储过程与在执行存储过程的内容执行相同的代码一个查询窗口显示非常不同的执行时间,但返回完全相同的183行结果集。通过EXEC SP执行相同的代码与在查询窗口中报告相同的结果EXEC SP代码,但不同的执行时间
的Test1执行从SSMS以下SP需要5分钟,以返回结果。
EXEC uspFleetSummaryReportSelectByDateCommand @UserID = 1468,@date = '2015年9月28日'
作为参考,这是SP细节:
CREATE PROCEDURE [dbo].[uspFleetSummaryReportSelectByDateCommand]
(
@UserID int,
@Date DateTime
)
AS
DECLARE @CustomerID int
SET @CustomerID = (Select CustomerID FROM [User] WHERE UserID = @UserID)
SELECT j.JourneyID,
j.DeviceID,
j.StartDate,
j.EndDate,
ISNULL(JourneyDistance, 0.0) AS [JourneyDistance],
CONVERT(VARCHAR(8), DATEADD(SECOND, DATEDIFF(SECOND, j.StartDate, j.EndDate), 0), 114) AS [Duration],
v.Registration,
v.InitOdometer,
jt.Name AS [JourneyType],
dt.Name AS [DeviceType],
PrivateJourney = (dbo.fxIsPrivateJourney(j.JourneyTypeID, j.DeviceID, @UserID)),
CONVERT(VARCHAR(8), DATEADD(SECOND, ISNULL(e.IdleTime, 0), 0), 114) AS [IdleTime]
FROM Journey j WITH (NOLOCK)
INNER JOIN Vehicle v WITH (NOLOCK) ON v.DeviceID = j.DeviceID
INNER JOIN JourneyType jt WITH (NOLOCK) ON jt.JourneyTypeID = j.JourneyTypeID
INNER JOIN Device d WITH (NOLOCK) ON d.DeviceID = j.DeviceID
INNER JOIN Configuration config WITH (NOLOCK) ON config.ConfigurationID = d.ConfigurationID
INNER JOIN DeviceType dt WITH (NOLOCK) ON dt.DeviceTypeID = config.DeviceTypeID
LEFT OUTER JOIN (
SELECT
e.JourneyId,
SUM(DATEDIFF(SECOND, e.StartDateTime, e.EndDateTime)) AS [IdleTime]
FROM [Event] e WITH (NOLOCK)
WHERE e.JourneyId = JourneyID AND e.EventType = 4/*Idle Event*/
GROUP BY e.JourneyId
) e ON e.JourneyId = j.JourneyID
WHERE j.StartDate BETWEEN @Date AND DATEADD(DAY,1,@Date)
AND (j.JourneyDistance IS NOT NULL)
AND DATEDIFF(MINUTE,j.StartDate,ISNULL(j.EndDate,getdate())) > 0
AND j.DeviceID IN (Select v.DeviceID
FROM Vehicle v WITH (NOLOCK)
INNER JOIN Customer c WITH (NOLOCK) ON c.CustomerID = v.CustomerID
INNER JOIN [User] u ON u.CustomerID = c.CustomerID
WHERE v.CustomerID = @CustomerID AND u.UserID = @UserID
AND (v.LevelOneID = u.LevelOneID Or u.LevelOneID is null)
AND (v.LevelTwoID = u.LevelTwoID Or u.LevelTwoID is null)
AND (v.LevelThreeID = u.LevelThreeID Or u.LevelThreeID is null)
AND (v.LevelFourID = u.LevelFourID Or u.LevelFourID is null)
AND (v.LevelFiveID = u.LevelFiveID Or u.LevelFiveID is null)
AND (v.DriverID = u.LevelSixID Or u.LevelSixID is null)
AND ISNULL(v.HideFromCustomer,0) != 1
)
ORDER BY Registration,j.JourneyID
的Test2
但执行相同的SP代码并设置变量需要10秒才能返回结果。
请在下面找到与变量集相同的SP。以下脚本从SSMS查询窗口执行。
DECLARE @UserID INT = 13651
DECLARE @Date DATETIME = '2015-09-28'
DECLARE @CustomerID int
SET @CustomerID = (Select CustomerID FROM [User] WHERE UserID = @UserID)
SELECT j.JourneyID,
j.DeviceID,
j.StartDate,
j.EndDate,
ISNULL(JourneyDistance, 0.0) AS [JourneyDistance],
CONVERT(VARCHAR(8), DATEADD(SECOND, DATEDIFF(SECOND, j.StartDate, j.EndDate), 0), 114) AS [Duration],
v.Registration,
v.InitOdometer,
jt.Name AS [JourneyType],
dt.Name AS [DeviceType],
PrivateJourney = (dbo.fxIsPrivateJourney(j.JourneyTypeID, j.DeviceID, @UserID)),
CONVERT(VARCHAR(8), DATEADD(SECOND, ISNULL(e.IdleTime, 0), 0), 114) AS [IdleTime]
FROM Journey j WITH (NOLOCK)
INNER JOIN Vehicle v WITH (NOLOCK) ON v.DeviceID = j.DeviceID
INNER JOIN JourneyType jt WITH (NOLOCK) ON jt.JourneyTypeID = j.JourneyTypeID
INNER JOIN Device d WITH (NOLOCK) ON d.DeviceID = j.DeviceID
INNER JOIN Configuration config WITH (NOLOCK) ON config.ConfigurationID = d.ConfigurationID
INNER JOIN DeviceType dt WITH (NOLOCK) ON dt.DeviceTypeID = config.DeviceTypeID
LEFT OUTER JOIN (
SELECT
e.JourneyId,
SUM(DATEDIFF(SECOND, e.StartDateTime, e.EndDateTime)) AS [IdleTime]
FROM [Event] e WITH (NOLOCK)
WHERE e.JourneyId = JourneyID AND e.EventType = 4/*Idle Event*/
GROUP BY e.JourneyId
) e ON e.JourneyId = j.JourneyID
WHERE j.StartDate BETWEEN @Date AND DATEADD(DAY,1,@Date)
AND (j.JourneyDistance IS NOT NULL)
AND DATEDIFF(MINUTE,j.StartDate,ISNULL(j.EndDate,getdate())) > 0
AND j.DeviceID IN (Select v.DeviceID
FROM Vehicle v WITH (NOLOCK)
INNER JOIN Customer c WITH (NOLOCK) ON c.CustomerID = v.CustomerID
INNER JOIN [User] u ON u.CustomerID = c.CustomerID
WHERE v.CustomerID = @CustomerID AND u.UserID = @UserID
AND (v.LevelOneID = u.LevelOneID Or u.LevelOneID is null)
AND (v.LevelTwoID = u.LevelTwoID Or u.LevelTwoID is null)
AND (v.LevelThreeID = u.LevelThreeID Or u.LevelThreeID is null)
AND (v.LevelFourID = u.LevelFourID Or u.LevelFourID is null)
AND (v.LevelFiveID = u.LevelFiveID Or u.LevelFiveID is null)
AND (v.DriverID = u.LevelSixID Or u.LevelSixID is null)
AND ISNULL(v.HideFromCustomer,0) != 1
)
ORDER BY Registration,j.JourneyID
调试至今
并排的两个语句侧比较它们是相同的栏变量的设置。
并排比较结果集,它们是相同的。
单独选择变量CUSTOMERID需要几毫秒。
传递的日期变量格式相同。
我们已经多次运行此测试来排除缓存相关问题。
查询执行计划在两次测试中都被检查过。在执行SP时,执行TEST1时清除了表EVENT上的索引。
指数升
CREATE NONCLUSTERED INDEX [290915_EventTypeJourneyID, EventTypeJID,>] ON [dbo].[Event]
(
[EventType] ASC,
[JourneyId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
结果
执行时间为TEST1下降到1秒。
问题
确定这样的原则问题就解决了,但是从根本上,我不明白为什么,基本上都运行相同的代码两次测试之间的性能差距?其相同的代码应该使用相同的索引,执行时间应该相似。
谢谢你对这种行为的任何见解。
参考
sql server 2008 64bit标准版。
Table.JOURNEY(350米行)
CREATE TABLE [dbo].[Journey](
[JourneyID] [int] IDENTITY(1,1) NOT NULL,
[StartAddress] [varchar](500) NULL,
[StartPostcode] [varchar](50) NULL,
[EndAddress] [varchar](500) NULL,
[EndPostcode] [varchar](50) NULL,
[JourneyTypeID] [int] NULL,
[Comment] [varchar](500) NULL,
[DriverID] [int] NULL,
[StartDate] [datetime] NULL,
[EndDate] [datetime] NULL,
[IdleTimeEngineOn] [int] NULL,
[TimeSinceLastJourney] [int] NULL,
[JourneyDistance] [decimal](8, 2) NULL,
[DeviceID] [int] NOT NULL,
[tempJourneyID] [int] NULL,
[tempCustomerID] [int] NULL,
CONSTRAINT [Journey_PK] PRIMARY KEY CLUSTERED
(
[JourneyID] 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].[Journey] WITH CHECK ADD CONSTRAINT [Device_Journey_FK1] FOREIGN KEY([DeviceID])
REFERENCES [dbo].[Device] ([DeviceID])
GO
ALTER TABLE [dbo].[Journey] CHECK CONSTRAINT [Device_Journey_FK1]
GO
ALTER TABLE [dbo].[Journey] WITH CHECK ADD CONSTRAINT [Driver_Journey_FK1] FOREIGN KEY([DriverID])
REFERENCES [dbo].[Driver] ([DriverID])
GO
ALTER TABLE [dbo].[Journey] CHECK CONSTRAINT [Driver_Journey_FK1]
GO
ALTER TABLE [dbo].[Journey] WITH NOCHECK ADD CONSTRAINT [JourneyType_Journey_FK1] FOREIGN KEY([JourneyTypeID])
REFERENCES [dbo].[JourneyType] ([JourneyTypeID])
GO
ALTER TABLE [dbo].[Journey] CHECK CONSTRAINT [JourneyType_Journey_FK1]
GO
Table.EVENT(36米行)
CREATE TABLE [dbo].[Event](
[EventID] [int] IDENTITY(1,1) NOT NULL,
[StartDateTime] [datetime] NULL,
[EndDateTime] [datetime] NULL,
[StartLocationID] [int] NOT NULL,
[EndLocationID] [int] NULL,
[AlertRaised] [bit] NULL,
[EventRuleID] [int] NULL,
[DeviceID] [int] NOT NULL,
[EventMessage] [varchar](max) NULL,
[TopSpeed] [decimal](4, 1) NULL,
[SpeedZone] [int] NULL,
[EventType] [int] NULL,
[ImpactId] [int] NULL,
[NotificationStatus] [bit] NULL,
[CableBreakZone0] [int] NULL,
[CableBreakDistance0] [int] NULL,
[CableBreakZone1] [int] NULL,
[CableBreakDistance1] [int] NULL,
[AdValue] [int] NULL,
[DriverId] [int] NULL,
[VehicleId] [int] NULL,
[JourneyId] [int] NULL,
CONSTRAINT [Event_PK] PRIMARY KEY CLUSTERED
(
[EventID] 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].[Event] WITH CHECK ADD CONSTRAINT [Device_Event_FK1] FOREIGN KEY([DeviceID])
REFERENCES [dbo].[Device] ([DeviceID])
GO
ALTER TABLE [dbo].[Event] CHECK CONSTRAINT [Device_Event_FK1]
GO
ALTER TABLE [dbo].[Event] WITH CHECK ADD CONSTRAINT [Event_Impact_FK] FOREIGN KEY([ImpactId])
REFERENCES [dbo].[Impact] ([ImpactID])
GO
ALTER TABLE [dbo].[Event] CHECK CONSTRAINT [Event_Impact_FK]
GO
ALTER TABLE [dbo].[Event] WITH CHECK ADD CONSTRAINT [EventRule_Event_FK1] FOREIGN KEY([EventRuleID])
REFERENCES [dbo].[EventRule] ([EventRuleID])
GO
ALTER TABLE [dbo].[Event] CHECK CONSTRAINT [EventRule_Event_FK1]
GO
ALTER TABLE [dbo].[Event] WITH CHECK ADD CONSTRAINT [FK_Event_Driver] FOREIGN KEY([DriverId])
REFERENCES [dbo].[Driver] ([DriverID])
GO
ALTER TABLE [dbo].[Event] CHECK CONSTRAINT [FK_Event_Driver]
GO
ALTER TABLE [dbo].[Event] WITH CHECK ADD CONSTRAINT [FK_Event_Journey] FOREIGN KEY([JourneyId])
REFERENCES [dbo].[Journey] ([JourneyID])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Event] CHECK CONSTRAINT [FK_Event_Journey]
GO
ALTER TABLE [dbo].[Event] WITH CHECK ADD CONSTRAINT [FK_Event_Vehicle] FOREIGN KEY([VehicleId])
REFERENCES [dbo].[Vehicle] ([VehicleID])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Event] CHECK CONSTRAINT [FK_Event_Vehicle]
GO
你分析了这么多,问问题的方式是明确的..very explantive – mohan111
您可能需要阅读有关参数嗅探 – Shnugo
另一个想法(特别是如果你的数据库有点老了...)可能是ARITHABORT,这也被称为造成奇怪的性能差异... – Shnugo