Проблема производительности по запросу - PullRequest
1 голос
/ 15 апреля 2010

У меня проблема с запросом.

Первая таблица - это таблица 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 ]

3 голосов
/ 15 апреля 2010

этот запрос примерно так же хорош, как если бы у вас был индекс для 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 голос
/ 15 апреля 2010

Вы упоминаете:

И то, что я хочу здесь, это; Как много раз адрес электронной почты в Таблица 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

Как это работает в вашем случае ??

1 голос
/ 15 апреля 2010

Использование условия OR лишает оптимизатор возможности использовать HASH JOIN или MERGE 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)

Первый запрос будет более эффективным, если ваши электронные письма в основном не заполнены, второй - если большинство электронных писем заполнены.

0 голосов
/ 15 апреля 2010

В зависимости от вашей среды, вы можете сделать немного, чтобы оптимизировать это.

Пара вопросов:

  1. Сколько записей в CommunicationInfo?
  2. Как часто вам действительно нужно выполнить этот запрос? Это однократный анализ, или несколько человек будут запускать его каждые 10 минут?
  3. Индексируются ли поля? Я сделаю предположение, что ни поле Email1, ни поле Email2 не проиндексированы. Однако я не рекомендовал бы добавлять индекс без учета баланса всей системы.
  4. Почему вы используете левое соединение? Вам действительно нужно ВСЕ из таблицы клиентов? Ты считаешь, так что не мешай делать ВНУТРЕННЕЕ СОЕДИНЕНИЕ

Предложения:

  1. Запустите запрос с помощью мастера оптимизации запросов, чтобы узнать, есть ли что-то, что SQL Server порекомендует.
  2. Крайним предложением было бы сбросить столбцы Email1 и Email2 во временную таблицу и присоединиться к ней. Я видел, что запросы выполняются медленно из-за большого количества нагрузки на конкретную таблицу, поэтому иногда копирование записей во временную таблицу происходит быстрее, но этот метод очень зависит от того, сколько памяти есть, какова скорость ввода-вывода, и величина стресса на конкретном столе.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...