Skip to content Skip to sidebar Skip to footer

Mssql - Making Multiple Count Distinct Calls In A Query Runs Slowly

I have tables with the following schema: Device DeviceId Name Service ServiceId Name Software SoftwareId Name Device_Software DeviceId SoftwareId DiscoveryDate Device_Servi

Solution 1:

I'd try the following and see if it makes difference :

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

You may also not need COUNT DISTINCT, but just COUNT with this version of query.

Solution 2:

You could consider indexed views on Device_Software and Device_Service:

CREATEVIEW dbo.v_Device_Software
WITH SCHEMABINDING
ASSELECT DeviceId, SoftwareId, DeviceCount = COUNT_BIG(*)
    FROM dbo.Device_Software
    GROUPBY DeviceId, SoftwareId;
GO
CREATEUNIQUE CLUSTERED INDEX x ON dbo.v_Device_Software(DeviceId, SoftwareId);
GO

CREATEVIEW dbo.v_Device_Service
WITH SCHEMABINDING
ASSELECT DeviceId, ServiceId, DeviceCount = COUNT_BIG(*)
    FROM dbo.Device_Service
    GROUPBY DeviceId, ServiceId;
GO
CREATEUNIQUE CLUSTERED INDEX x ON dbo.v_Device_Service(DeviceId, ServiceId);
GO

Now your query becomes:

SELECT
  device.name
  ,COUNT(vsoft.DeviceId)
  ,COUNT(vserv.DeviceId)
FROM
  dbo.device
LEFTOUTERJOIN dbo.v_Device_Service AS vserv
  ON device.deviceId = vserv.DeviceId
LEFTOUTERJOIN dbo.v_Device_Software AS vsoft
  ON device.deviceId = voft.DeviceId
GROUPBY device.name;

There are many restrictions, though, and you should be sure to test the impact this has on your entire workload, not just this one query.

Post a Comment for "Mssql - Making Multiple Count Distinct Calls In A Query Runs Slowly"