查询的性能问题

时间:2010-04-15 17:13:20

标签: sql-server tsql

我的查询存在性能问题。

第一个表是一个Customer表,其中包含数百万条记录。客户表有一列电子邮件地址和一些其他有关客户的信息。

第二个表是一个CommunicationInfo表,它只包含电子邮件地址。

我想要的是这里; CommunicationInfo表中的电子邮件地址在Customers表中重复的次数。什么是表现最好的查询。

我可以解释这种情况的基本查询是;

Select ci.Email, count(*) from Customer c left join 
CommunicationInfo ci on c.Email1 = ci.Email or c.Email2 = ci.Email 
Group by ci.Email

但可以肯定的是,执行大约需要5,6分钟。

先谢谢。

4 个答案:

答案 0 :(得分:3)

如果您在Customer.Email上有索引,而另一个在CommunicationInfo.Email

上有索引,那么这个查询就好了。
Select
    c.Email, count(*)
    from Customer c
        left join CommunicationInfo  ci on c.Email1 = ci.Email
        left join CommunicationInfo ci2 on c.Email2 = ci2.Email
    Group by c.Email

答案 1 :(得分:1)

使用OR条件会剥夺优化机会使用HASH JOINMERGE JOIN

使用此:

SELECT  ci.Email, SUM(cnt)
FROM    (
        SELECT  ci.Email, COUNT(c.Email) AS cnt
        FROM    CommunicationInfo ci
        LEFT JOIN
                Customer c
        ON      c.Email1 = ci.Email
        GROUP BY
                ci.Email
        UNION ALL
        SELECT  ci.Email, COUNT(c.Email) AS cnt
        FROM    CommunicationInfo ci
        LEFT JOIN
                Customer c
        ON      c.Email2 = ci.Email
        GROUP BY
                ci.Email
        ) q2
GROUP BY
        ci.Email

或者这个:

SELECT  ci.Email, COUNT(*)
FROM    CommunicationInfo ci
LEFT JOIN
        (
        SELECT  Email1 AS email
        FROM    Customer c
        UNION ALL
        SELECT  Email2
        FROM    Customer
        ) q
ON      q.Email = ci.Email
GROUP BY
        ci.Email

确保您在Customer(Email)Customer(Email2)

上拥有索引

如果您的电子邮件大部分未填写,第一个查询将更有效,第二个查询 - 如果大多数电子邮件已填满,则会更有效。

答案 2 :(得分:1)

你提到:

  

我想要的是这里;多少   倍于电子邮件地址   CommunicationInfo表重复   客户表。可能是什么   表演者最多的查询。

对我来说,听起来你可以很容易地使用INNER JOIN - 这很可能会快得多,因为它会将搜索范围限制在那些真正拥有电子邮件的客户身上 - 任何人都不会根本没有电子邮件(因此计数(*)= 0)甚至不会被看到 - 即使只是SQL Server必须计算和分组的行数,这可能会产生很大的不同。

所以试试这个:

SELECT 
   ci.Email, COUNT(*) 
FROM 
   dbo.Customer c 
INNER JOIN dbo.CommunicationInfo ci 
   ON c.Email1 = ci.Email OR c.Email2 = ci.Email  
GROUP BY
   ci.Email

在你的情况下如何表现?

答案 3 :(得分:0)

根据您的环境,您可能无法对此进行优化。

几个问题:

  1. CommunicationInfo中有多少条记录?
  2. 您多久需要运行此查询?这是一次性分析,还是每10分钟会有多个人运行?
  3. 字段是否已编入索引?我猜测Email1和Email2字段都没有编入索引。但是,我不建议在不考虑整个系统平衡的情况下添加索引。
  4. 你为什么要使用左连接?你真的需要Customer表中的所有内容吗?你在计算,所以在做INNER JOIN时没有坏处。
  5. 建议:

    1. 通过“查询优化”向导运行查询,以查看SQL Server是否会推荐任何内容。
    2. 极端的建议是将Email1和Email2列转储到临时表中并加入到该表中。我看到由于特定表上的大量压力而导致查询运行缓慢,因此有时将记录复制到临时表更快,但这种技术非常依赖于存储的内存,IO的速度以及特定桌子上的压力。