我有两张桌子:
CREATE TABLE [dbo].[CustomerEmails](
[id] [int] IDENTITY(1,1) NOT NULL,
[datecreated] [datetime] NULL,
[UID] [nvarchar](250) NULL,
[From] [nvarchar](100) NULL,
[To] [nvarchar](100) NULL,
[Subject] [nvarchar](max) NULL,
[Body] [nvarchar](max) NULL,
[Dated] [datetime] NULL,
CONSTRAINT [PK_CustomerEmails] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
)
CREATE TABLE [dbo].[CustomerEmailIds](
[Email] [varchar](200) NULL
) ON [PRIMARY]
您可能在想我为什么不在表CustomerEmails中使用EmailId而不是使用电子邮件本身?我的意思是我可以将一列EmailId(INT)添加到表CustomerEmailIds&然后我可以引用该列而不是CustomerEmails.From& CustomerEmails.To?伙计问题是表CustomerEmails被其他一些应用程序使用&该应用程序只是跟踪通过OutLook发送/接收的电子邮件。表CustomerEmailIds有客户电子邮件&这些电子邮件从我正在处理的应用程序进入系统。
因此,表CustomerEmails有7,00,000多条记录,而表CustomerEmailIds有1,00,000多条记录。
我需要根据CustomerEmailIds表中的电子邮件找到来自CustomerEmails表的电子邮件。
我正在使用的查询是:
SELECT
e.*
FROM CustomerEmails e
WHERE EXISTS
(
SELECT Email
FROM CustomerEmailIds c
WHERE ( ISNULL(e.[From],'') + '/' + ISNULL(e.[To],'') ) LIKE '%'+c.Email+'%'
)
Some facts:
1- I am using SQL Server 2008
2- Sorry guys, i forgot to mention that the CustomerEmails.**To** can contains multiple comma separated emails like: email1@yahho.com,email2@yahho.com,email3@yahho.com
3- Because of the fact2 the c.Cs3Emails+'%' OR to= c.Cs3Emails will not list the desired results that's why i am using '%'+c.Cs3Emails+'%'
最新调查结果: 伙计上面的查询返回错误的结果.....&我不知道为什么?
但是下面的查询工作正常:
SELECT
e.*
FROM CustomerEmails e
WHERE (ISNULL(e.[From],'') + '/' + ISNULL(e.[To],'')) LIKE '%email1@gmail.com%'
答案 0 :(得分:3)
雅各布, 查询中的where子句永远不会使用索引。 这是因为有两个问题:
1)你正在进行字符串连接以进行比较
ISNULL(e.[From],'') + '/' + ISNULL(e.[To],'') )
2)你喜欢
后两端使用外卡LIKE '%'+c.Cs3Emails+'%'
为了优化,我建议这样做:
1)您创建另一列以存储电子邮件的连接值。 额外的存储,但这将使您免于运行缓慢。 然后,您可以在该列上创建索引以加快速度。
2)您是否可以更改类似条件?
LIKE c.Cs3Emails+'%'
从开头删除%
可能会使用索引(如果c.Cs3Emails上有任何内容)
希望这有帮助
答案 1 :(得分:2)
这部分查询:
WHERE ( ISNULL(e.[From],'') + '/' + ISNULL(e.[To],'') ) LIKE '%'+c.Cs3Emails+'%'
强制执行全表扫描,因为它使用WHERE
子句中的函数,并且因为类似'%....%' - 开头的%符号。你可以重写那个部分来使用字段/常量吗?
您应该让您的查询在索引字段中受益 - 例如,如果您在字段c.Cs3Emails
上有索引,那么您的查询应该看起来像
WHERE c.Cs3Emails = 'some_value_here'
some_value_here
值不应该是函数输出的结果(如果这是可能的话)
即使您的查询看起来像
WHERE c.Cs3Emails = 'some_value_here%'
可以使用索引,但不能使用
WHERE c.Cs3Emails = '%some_value_here%'
因为在这里,就像你会试着在名字的第二个字母之后找到电话簿。
尝试详细了解database indexes以及如何使用它们
此外,我认为您可以重写您的查询:
SELECT
e.*
FROM Emails e
WHERE EXISTS
(
SELECT Cs3Emails
FROM Cs3EmailsForPurge c
WHERE e.From = c.Cs3Emails OR e.To = c.Cs3Emails
)
请尝试此查询,看看它是否返回与您相同的结果
如果我的查询返回相同的结果集并且性能没有提高,请在字段Emails.From
上添加索引,在Emails.To
上添加索引。这将改善您的查询执行时间。
答案 2 :(得分:2)
这个查询背后的想法是有缺陷的。我知道您正在尝试使用跟踪编号将消息链接在一起,可能在主题行中,但这应该起作用的方式是,当电子邮件导入数据库时,应找到他们的跟踪编号,然后将其提取到自己的领域。通过这种方式,您可以为每次导入付出轻微的打击,但在查询数据时可以获得巨大的好处。
我建议您更新当前数据并重写导入。该查询不会再获得更高的性能。
答案 3 :(得分:0)
答案 4 :(得分:0)
好人们首先看一下返回错误结果的查询:
SELECT
e.*
FROM CustomerEmails e
WHERE EXISTS
(
SELECT Email
FROM CustomerEmailIds c
WHERE ( ISNULL(e.[From],'') + '/' + ISNULL(e.[To],'') ) LIKE '%'+c.Email+'%'
)
此查询没有问题,问题是CustomerEmailIds表中的某些电子邮件是无效的电子邮件('。','@','0',' - ')&这就是为什么查询返回存在这些无效电子邮件的所有CustomerEmails的原因。