2013-03-28 49 views
4

我有兩個表:「報警」和「設備」和視圖「vwAlarms」 報警表有250K行,設備表只有50行。按連接表的性能問題排序

vwAlarms只是兩個表的連接。

我的問題是當我添加Top(x)和命令ID desc從vwAlarm中選擇*需要10秒鐘來執行查詢。然而相同的查詢在表格報警上快速運行。

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 
+0

你從視圖返回什麼?具體來說,來自「報警」或「設備」表的「ID」還是其他? – Guffa

+0

@Guffa:我返回查看兩個表的所有列。 id是來自Alarms Table –

+0

什麼是視圖定義? – TToni

回答

1

這不是很聰明。
您是否定義了FK?

我會嘗試連接上的表提示的所有選項,以嘗試更早的推送。

Join Hints (Transact-SQL)

如果表提示不工作,我會嘗試跨應用。
我認爲交叉應用應該聰明點。
但代價是沒有像「加入」一樣快。
因此,它可以很好地返回前1000或10,000,但不好。

SELECT t1.*, t2o.* 
FROM t1 
CROSS APPLY 
     (
     SELECT * 
     FROM t2 
     WHERE t2.t1_id = t1.id 
     ) t2o 
+0

是的,它有FK。請參閱警報表定義,讓我研究加入提示謝謝,我會回來。 –

+0

我已經應用了聯合提示。但沒有得到任何性能提升 –

+0

創建包含鬧鐘表的最後100條記錄的臨時表,並將連接應用於此表是否正確? –

1

正在使用視圖必須?如果沒有,你可能應該先獲得100個警報,然後加入設備。這是你想要的最終結果?

+0

沒有它沒有必要,我想我應該你一個存儲過程,首先選擇最後100個警報,並將其存儲在臨時表中,它加入並返回結果。謝謝 –