4

「アラーム」と「デバイス」の 2 つのテーブルと「vwAlarms」ビューがあります。アラーム テーブルには 250K 行があり、デバイス テーブルには 50 行しかありません。

vwAlarms は 2 つのテーブルを結合したものです。

私の問題は、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 
4

2 に答える 2

1

ビューの使用は必須ですか? そうでない場合は、最初に 100 個のアラームを取得してから、デバイスに参加する必要があります。それがあなたが望む最終結果ですよね?

于 2013-03-28T15:59:16.980 に答える
1

ソートについてはスマートではありません。
FK が定義されていますか?

結合でテーブルヒントのすべてのオプションを試して、そのソートをより早くプッシュしようとします。

結合ヒント (Transact-SQL)

テーブル ヒントが機能しない場合は、クロス適用を試みます。
クロスアプライはソートについてスマートであるべきだと思います。
しかし、「結合」でそれほど速くないという犠牲を払って。
したがって、最初の 1000 または 10,000 を返すのは良いことですが、まったく悪いことです。

SELECT  t1.*, t2o.*
FROM    t1
CROSS APPLY
        (
        SELECT *
        FROM    t2
        WHERE   t2.t1_id = t1.id
        ) t2o 
于 2013-03-28T15:29:57.637 に答える