按联合表格的性能问题排序

时间:2013-03-28 13:03:41

标签: sql-server tsql join

我有两个表:“警报”和“设备”以及视图“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

这是执行计划: enter image description here

排序警告信息: enter image description here

警报表架构:

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 

2 个答案:

答案 0 :(得分:1)

关于这种情况并不聪明 你有FK定义吗?

我会尝试连接上的表提示的所有选项,以尝试更早地推送该类。

Join Hints (Transact-SQL)

如果表格提示不起作用,我会尝试交叉申请 我认为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个警报,然后加入设备。那是你想要的最终结果吗?