首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >MSSQL -在查询中执行多个计数不同的调用,运行缓慢。

MSSQL -在查询中执行多个计数不同的调用,运行缓慢。
EN

Stack Overflow用户
提问于 2012-08-29 16:43:36
回答 2查看 1.3K关注 0票数 1

我有具有以下模式的表:

设备

  • DeviceId
  • 名字

服务

  • ServiceId
  • 名字

软件

  • SoftwareId
  • 名字

Device_Software

  • DeviceId
  • SoftwareId
  • DiscoveryDate

Device_Service

  • DeviceId
  • ServiceId
  • DiscoveryDate

现在,我正在尝试编写一个查询,给出一个设备,以及设备拥有的不同软件和服务的数量。

如果我运行以下查询,我将在5秒内得到一个结果(设备有50,000行,软件和服务都有200行,链接表包括每个设备到每个软件和服务的链接)。只是为了测试的目的)。

代码语言:javascript
代码运行次数:0
运行
复制
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分钟,并且仍在继续):

代码语言:javascript
代码运行次数:0
运行
复制
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

既然这是在存储过程中,我可以单独获取这两个计数并将其合并,但这似乎是一次黑客攻击。我在想,是否有人知道有更好的方法可以在一个查询中做到这一点,而不影响性能呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-08-29 17:00:52

我会尝试以下几种方法,看看它是否起作用:

代码语言:javascript
代码运行次数:0
运行
复制
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

票数 2
EN

Stack Overflow用户

发布于 2012-08-29 16:50:13

您可以考虑在Device_Software和Device_Service上建立索引视图:

代码语言:javascript
代码运行次数:0
运行
复制
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

现在,您的查询变成:

代码语言:javascript
代码运行次数:0
运行
复制
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;

但是有许多限制,您应该确保测试这对整个工作负载的影响,而不仅仅是这个查询。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12182704

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档