我一直在编写一个流程来根据特定的业务规则评估计算机,以确定它们是否有资格在其上安装产品。我最初使用的是一个小型SQLite数据库,但该项目开始变得足够大,以至于我将其转换为MS SQL Server。数据库中有大约500k行。
在SQLite上花费大约30秒的查询在SQL服务器上花了将近30分钟。我希望它会快得多,因为我正在迁移到拥有更多系统资源的专用服务器。
查询如下。基本思想是我有一个包含计算机信息的表和一个包含规则的表,并且需要将不同的规则与计算机信息表中的不同列进行比较。我还需要考虑"包含" - 如果计算机具有包含规则,则优先于任何排除规则。
我对SQL来说相当新,所以它可能只是一个写得不好的查询,但它似乎提供了预期的结果。它的速度太慢了。
WITH RulesWith
AS (
SELECT *
FROM Rules
WHERE
productName = 'Dlp'
AND (
_dateEffective IS NULL
OR _dateEffective <= '20160906'
)
AND (
_dateExpired IS NULL
OR _dateExpired >= '20160906'
)
)
SELECT C.*
FROM Computers AS C
WHERE (
(
C._dateEffective IS NULL
OR C._dateEffective <= '20160906'
)
AND (
C._dateExpired IS NULL
OR C._dateExpired >= '20160906'
)
)
AND (
(
C.site_name IN (
SELECT value
FROM RulesWith
WHERE propertyName = 'Site'
AND typeName = 'Include'
)
OR C.computer_fqdn IN (
SELECT value
FROM RulesWith
WHERE propertyName = 'Computer'
AND typeName = 'Include'
)
OR C.computer_ou IN (
SELECT value
FROM RulesWith
WHERE propertyName = 'ComputerOU'
AND typeName = 'Include'
)
OR C.user_ou IN (
SELECT value
FROM RulesWith
WHERE propertyName = 'UserOU'
AND typeName = 'Include'
)
)
OR NOT (
C.site_name IN (
SELECT value
FROM RulesWith
WHERE propertyName = 'Site'
AND typeName = 'Exclude'
)
OR C.computer_fqdn IN (
SELECT value
FROM RulesWith
WHERE productName = 'MyProduct'
AND propertyName = 'Computer'
AND typeName = 'Exclude'
)
OR C.computer_ou IN (
SELECT value
FROM RulesWith
WHERE propertyName = 'ComputerOU'
AND typeName = 'Exclude'
)
OR C.user_ou IN (
SELECT value
FROM RulesWith
WHERE propertyName = 'UserOU'
AND typeName = 'Exclude'
)
)
)
编辑:删除大量UPPER()函数可将查询时间大幅缩短至约5分钟。我仍然希望进一步清理它,但这是一个巨大的差异。