1

次のスキーマを持つテーブルがあります。

デバイス

  • デバイスID
  • 名前

サービス

  • サービス ID
  • 名前

ソフトウェア

  • ソフトウェア ID
  • 名前

デバイス_ソフトウェア

  • デバイスID
  • ソフトウェア ID
  • 発見日

デバイス_サービス

  • デバイスID
  • サービス ID
  • 発見日

ここで、デバイスと、そのデバイスが持つ個別のソフトウェアとサービスの数を与えるクエリを作成しようとしています。

次のクエリを実行すると、5 秒以内に結果が返されます (デバイスには 50,000 行、ソフトウェアとサービスには両方とも 200 行があり、リンク テーブルにはすべてのデバイスからすべてのソフトウェアとサービスへのリンクが含まれています。テスト目的のためだけです)。

SELECT
  device.name
  ,COUNT(DISTINCT(device_software.softwareId))
FROM
  device
LEFT OUTER JOIN
  device_software ON device.deviceId = device_software.deviceId
GROUP BY device.name

ただし、両方のカウントを含めるようにクエリを拡張しようとすると、はるかに時間がかかります (〜 30 分、まだ続きます)。

SELECT
  device.name
  ,COUNT(DISTINCT(device_software.softwareId))
  ,COUNT(DISTINCT(device_service.serviceId))
FROM
  device
LEFT OUTER JOIN
  device_service ON device.deviceId = device_service.deviceId
LEFT OUTER JOIN
  device_software ON device.dDeviceId = device_software.deviceId
GROUP BY device.name

これはストアド プロシージャにあるため、2 つのカウントを個別に取得して結合することもできますが、これはハックのように思えます。パフォーマンスに大きな影響を与えることなく、単一のクエリでこれを行うためのより良い方法を誰かが知っているかどうか疑問に思っていましたか?

4

2 に答える 2

2

私は次のことを試して、それが違いを生むかどうかを確認します:

SELECT
device.name
a.cntSft, b.cntSrv
FROM device
LEFT JOIN
 ( SELECT deviceId, COUNT(DISTINCT softwareId) as cntSft FROM device_software 
 GROUP BY deviceId) a (ON a.deviceId = device.deviceId)
LEFT JOIN 
( SELECT deviceId, COUNT(DISTINCT serviceId) as cntSrv FROM device_service 
 GROUP BY deviceId) b (ON b.deviceId = device.deviceId);

も必要ないかもしれませんが、このバージョンのクエリを使用するCOUNT DISTINCTだけです。COUNT

于 2012-08-29T17:00:52.380 に答える
0

Device_SoftwareとDevice_Serviceのインデックス付きビューを検討できます。

CREATE VIEW dbo.v_Device_Software
WITH SCHEMABINDING
AS
  SELECT DeviceId, SoftwareId, DeviceCount = COUNT_BIG(*)
    FROM dbo.Device_Software
    GROUP BY DeviceId, SoftwareId;
GO
CREATE UNIQUE CLUSTERED INDEX x ON dbo.v_Device_Software(DeviceId, SoftwareId);
GO

CREATE VIEW dbo.v_Device_Service
WITH SCHEMABINDING
AS
  SELECT DeviceId, ServiceId, DeviceCount = COUNT_BIG(*)
    FROM dbo.Device_Service
    GROUP BY DeviceId, ServiceId;
GO
CREATE UNIQUE CLUSTERED INDEX x ON dbo.v_Device_Service(DeviceId, ServiceId);
GO

これで、クエリは次のようになります。

SELECT
  device.name
  ,COUNT(vsoft.DeviceId)
  ,COUNT(vserv.DeviceId)
FROM
  dbo.device
LEFT OUTER JOIN dbo.v_Device_Service AS vserv
  ON device.deviceId = vserv.DeviceId
LEFT OUTER JOIN dbo.v_Device_Software AS vsoft
  ON device.deviceId = voft.DeviceId
GROUP BY device.name;

ただし、多くの制限があり、これが1つのクエリだけでなく、ワークロード全体に与える影響を必ずテストする必要があります。

于 2012-08-29T16:50:13.037 に答える