我有两个表:“警报”和“设备”以及视图“vwAlarms” 报警表有250K行,设备表只有50行。
vwAlarms只是两个表的连接。
我的问题是当我添加Top(x)并通过id desc命令从vwAlarm中选择*时,执行查询需要10秒。但是相同的查询在表Alarm上快速运行。
select * from Alarm --in milliseconds.
select * from vwAlarms --in milliseconds
select top (100) * from Alarms order by id desc --in milliseconds
select top (100) * from vwAlarms order by id desc --takes 10 seconds
以下是我的观点定义:
CREATE VIEW [dbo].[vwAlarms]
AS SELECT
dbo.Devices.Id ,
dbo.Devices.Name ,
dbo.Devices.PortsTagPrefix ,
dbo.Devices.ControlCenterNumber ,
dbo.Devices.AlarmNumber1 ,
dbo.Devices.AlarmNumber2 ,
dbo.Devices.SimCardNumber ,
dbo.Devices.StationNumber ,
dbo.Devices.SlaveId ,
dbo.Devices.TypeId ,
dbo.Devices.RegionId ,
dbo.Devices.EnquiryPassword ,
dbo.Devices.SetupPassword ,
dbo.Devices.ProtocolId ,
dbo.Devices.UploadedPacketsCount ,
dbo.Devices.LastPort ,
dbo.Devices.LastIp ,
dbo.Devices.IsForTesting ,
dbo.Devices.Latitude ,
dbo.Devices.Longitude ,
dbo.Devices.X ,
dbo.Devices.Y ,
dbo.Devices.MainSchematicId ,
dbo.Devices.MainTimeChartId ,
dbo.Devices.MainCategoryChartId ,
dbo.Alarms.Id ,
dbo.Alarms.DeviceId ,
dbo.Alarms.LogId ,
dbo.Alarms.PortId ,
dbo.Alarms.TypeId ,
dbo.Alarms.DateTime ,
dbo.Alarms.AcknowledgerId ,
dbo.Alarms.AcknowledgeDateTime ,
dbo.Alarms.Acknowledged ,
dbo.Alarms.PortValue
FROM Devices
INNER JOIN Alarms ON Devices.Id = Alarms.DeviceId
ORDER BY dbo.Alarms.Id DESC
这是执行计划:
排序警告信息:
警报表架构:
CREATE TABLE [dbo].[Alarms](
[Id] [int] IDENTITY(1,1) NOT NULL,
[DeviceId] [int] NOT NULL,
[LogId] [int] NOT NULL,
[PortId] [int] NOT NULL,
[TypeId] [int] NOT NULL,
[DateTime] [datetime2](0) NOT NULL,
[AcknowledgerId] [int] NULL,
[AcknowledgeDateTime] [datetime2](0) NULL,
[Acknowledged] [bit] NULL,
[PortValue] [numeric](19, 4) NULL,
CONSTRAINT [PK_Alarms] PRIMARY KEY CLUSTERED
(
[Id] 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
ALTER TABLE [dbo].[Alarms] WITH CHECK ADD CONSTRAINT [FK_Alarms_AlarmTypes] FOREIGN KEY([TypeId])
REFERENCES [dbo].[AlarmTypes] ([Id])
GO
ALTER TABLE [dbo].[Alarms] CHECK CONSTRAINT [FK_Alarms_AlarmTypes]
GO
ALTER TABLE [dbo].[Alarms] WITH CHECK ADD CONSTRAINT [FK_Alarms_Devices] FOREIGN KEY([DeviceId])
REFERENCES [dbo].[Devices] ([Id])
GO
ALTER TABLE [dbo].[Alarms] CHECK CONSTRAINT [FK_Alarms_Devices]
GO
ALTER TABLE [dbo].[Alarms] WITH CHECK ADD CONSTRAINT [FK_Alarms_ExtendedUsers] FOREIGN KEY([AcknowledgerId])
REFERENCES [dbo].[ExtendedUsers] ([Id])
GO
ALTER TABLE [dbo].[Alarms] CHECK CONSTRAINT [FK_Alarms_ExtendedUsers]
GO
ALTER TABLE [dbo].[Alarms] WITH CHECK ADD CONSTRAINT [FK_Alarms_Logs] FOREIGN KEY([LogId])
REFERENCES [dbo].[Logs] ([Id])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER
答案 0 :(得分:1)
关于这种情况并不聪明 你有FK定义吗?
我会尝试连接上的表提示的所有选项,以尝试更早地推送该类。
如果表格提示不起作用,我会尝试交叉申请 我认为Cross Apply应该对排序很聪明 但代价是没有像“加入”一样快 因此,返回前1000或10,000但是很糟糕会很好。
SELECT t1.*, t2o.*
FROM t1
CROSS APPLY
(
SELECT *
FROM t2
WHERE t2.t1_id = t1.id
) t2o
答案 1 :(得分:1)
是否必须使用视图?如果没有,您可能应首先获得100个警报,然后加入设备。那是你想要的最终结果吗?