我在一个包含300万条比较电子邮件地址的记录的表上运行SQL查询。
我们有两个电子邮件地址字段,主要和次要。
我正在将主要电子邮件的子集与所有其他主要和次要电子邮件进行比较,以计算数据中的重复项和唯一电子邮件的数量。
我相信这个代码有效,它仍然运行10分钟,我必须为另外9个子集做这个,这个子集比这个要大很多。代码如下:
SELECT COUNT(*) AS UniqueRecords
FROM AllVRContacts
WHERE LEN(EMAIL) > 1 AND ACCOUNTID = '00120000003bNmMAAU'
AND EMAIL NOT IN
(SELECT EMAIL FROM AllVRContacts WHERE ACCOUNTID != '00120000003bNmMAAU')
AND EMAIL NOT IN
(SELECT SECONDARY_EMAIL_ADDRESS__C FROM AllVRContacts WHERE ACCOUNTID != '00120000003bNmMAAU')
我想从中学到一些东西,而不仅仅是有人为我刮伤我的背,越多的解释越好!
谢谢你们,
答案 0 :(得分:2)
创建以下索引:
AllVrContacts (AccountID) INCLUDE (Email)
AllVrContacts (Email) INCLUDE (AccountID)
AllVrContacts (SECONDARY_EMAIL_ADDRESS__C) INCLUDE (AccountID)
(AccountID, Email)
上的索引将用于主查询中的WHERE
过滤器:
WHERE ACCOUNTID = '00120000003bNmMAAU'
AND LEN(Email) > 1
其他两个索引将用于针对此表的反连接(NOT IN
)。
您还应该使用:
SELECT COUNT(DISTINCT email) AS UniqueRecords
如果您希望同一帐户中的重复项只计算一次。
答案 1 :(得分:1)
SELECT COUNT(*)
FROM (SELECT EMAIL AS UniqueRecords
FROM AllVRContacts a
WHERE ACCOUNTID = '00120000003bNmMAAU'
AND NOT EXISTS (SELECT EMAIL FROM AllVRContacts b
WHERE ACCOUNTID != '00120000003bNmMAAU'
AND (
a.EMAIL = b.EMAIL
OR a.EMAIL = b.SECONDARY_EMAIL_ADDRESS__C
)
)
AND LEN(EMAIL) > 1
GROUP BY EMAIL
) c
那么这个查询怎么更好?
您通常希望使用NOT EXISTS而不是NOT IN
如果指定的值与子查询或列表中的任何值匹配,则 IN
返回true
EXISTS
返回true
更多信息:SQL Server: JOIN vs IN vs EXISTS - the logical difference
=比!=
通过不再通过AllVRContacts搜索辅助电子邮件比较来减少扫描(寻找在AllVRContacts上有索引)
GROUP BY
解决了ACCOUNTID内潜在的重复电子邮件
为了进一步提高性能,按照Quassnoi的建议添加索引,填充表格的任何内容都应该验证电子邮件,以消除对LEN检查的需要。
[编辑]向(3)
添加了解释答案 2 :(得分:1)
这可以适用吗?
SELECT ACCOUNTID, COUNT(*) AS UniqueRecords
FROM (
SELECT ACCOUNTID, EMAIL
FROM AllVRContacts
WHERE ACCOUNTID = '00120000003bNmMAAU' AND LEN(EMAIL) > 1
UNION
SELECT ACCOUNTID, SECONDARY_EMAIL_ADDRESS__C
FROM AllVRContacts
WHERE ACCOUNTID = '00120000003bNmMAAU' AND LEN(SECONDARY_EMAIL_ADDRESS__C) > 1
) s
据我所知,基本上你想为每个ACCOUNTID计算不同的电子邮件地址。
内部查询中的UNION消除了重复项,因此(内部查询的)输出只有不同的帐户ID和电子邮件对,无论是主要还是次要。特别是这意味着如果电子邮件地址同时存储为主要和次要,它将只计数一次。同样适用于存储在不同行中的相同主要或相同的辅助地址。
现在你只需要计算行数,这是由外部查询完成的。
如果您提到的其他9个子集仅指其他ACCOUNTID,那么您可以尝试将GROUP BY ACCOUNTID
应用于外部查询,并且ACCOUNTID = '...'
两个WHERE
部分的SELECT ACCOUNTID, COUNT(*) AS UniqueRecords
FROM (
SELECT ACCOUNTID, EMAIL
FROM AllVRContacts
WHERE LEN(EMAIL) > 1
UNION
SELECT ACCOUNTID, SECONDARY_EMAIL_ADDRESS__C
FROM AllVRContacts
WHERE LEN(SECONDARY_EMAIL_ADDRESS__C) > 1
) s
GROUP BY ACCOUNTID
部分都可以删除使用一个查询计算所有这些邮件的电子邮件。就是这样:
{{1}}
答案 3 :(得分:0)
试试这个并告诉我
SELECT ACCOUNTID,COUNT(*)AS UniqueRecords
来自AllVRContacts
LERE(EMAIL)> 1 AND ACCOUNTID ='00120000003bNmMAAU'
由ACCOUNTID集团
有COUNT(EMAIL)> 1