Очень медленный SQL-запрос к серверу - PullRequest
0 голосов
/ 07 октября 2009

У меня есть 2 таблицы, полученные в результате объединения следующих таблиц:

Authors
 -Aid bigint
 -Surname nvarchar(500)
 -Email nvarchar(500)

Articles
 -ArId varchar(50)
 -Year int
 -……Some other fields……

ArticleAuthors
 -ArId varchar(50)
 -Aid bigint

Classifications
 -ClassNumber int
 -ClassDescription nvarchar(100)

ClassArticles
 -ArId varchar(50)
 -ClassNumber int

После денормализации этих таблиц были получены следующие таблицы:

Articles
 -FieldId int
 -ArId varchar(50)
 -ClassNumber int (Foreign key from the Classifications table)
 -Year int

Authors
 -FieldId int
 -ArId varchar(50) (Foreign key from the Articles table)
 -Aid bigint
 -Surname nvarchar(500)
 -Email nvarchar(500)
 -Year int

Вот условия данных в приведенных таблицах:

  • База данных SQL Server 2008
  • Отношения между двумя таблицами применяются физически
  • Таблица авторов содержит 50 миллионов записей
  • Таблица статей содержит 20 миллионов записей
  • Автор написал много статей за один и тот же год с разными электронными письмами
  • В таблице авторов есть авторы с идентификаторами ArIds, которые не ссылаются на идентификаторы ArIds в таблице «Статьи» (записи об ошибках)
  • Значения в полях года варьируются от 2002 до 2009
  • Таблица Articles имеет уникальный кластеризованный индекс в полях [FieldId и Year], и этот индекс создается на 9 разделах (1 раздел в год)
  • Таблица «Авторы» имеет неуникальный кластеризованный индекс в полях [Year, ArId, Aid], и этот индекс создается в том же 9-м разделе, что и таблица «Articles» (1 раздел в год)

Вопрос:

  • Нам нужно создать хранимую процедуру, которая получает следующий результат из двух таблиц [Помощь, Фамилия, Электронная почта] при следующих условиях:

  • Авторы, написавшие статьи в течение и после определенного года (И)

  • Общее количество статей для автора больше определенного числа (И)
  • Количество статей, написанных автором под конкретным ClassNumber, превышает определенный процент от общего количества его статей (AND)
  • Получить только самое последнее письмо автора (за последний год, в течение которого он написал статью)
  • Если у автора более одного письма за один и тот же год, получите их все.

Нам нужно, чтобы запрос занял как можно меньше времени

Если кто-то может помочь, большое спасибо.

Ответы [ 4 ]

2 голосов
/ 07 октября 2009

Без этих данных очень сложно работать, но я создал таблицы и продублировал процедуру, чтобы получить общее представление о плане запроса и потенциальных проблемах.

Первая заметная вещь, часть запроса, записанная в виде:

SELECT DISTINCT Aid 
FROM Authors EAE 
WHERE EAE.[Year] >= @year AND EAE.Email IS NOT NULL AND EAE.Email != ' '

Идет сканирование таблицы, в качестве ключа разделения у вас есть Год, но внутри каждого раздела нет индекса, поддерживающего предложения электронной почты в запросе. Как примечание стороны, EAE.Email! = '' Может не дать вам того, что вы ожидаете. Если ''! = '' Напечатать 'true', иначе вывести 'false' Это даст ложь для большинства систем. (На основе данных)

FROM Articles ED 
INNER JOIN Authors EAD ON EAD.ArId = ED.ArId 
WHERE EAD.Aid = [YearAuthors].Aid AND ED.ClassNumber = @classNumber

ED.ClassNumber не будет иметь поддерживающего индекса, что приведет к сканированию кластеризованного индекса.

В последнем утверждении выбора: ВНУТРЕННЕЕ СОЕДИНЕНИЕ Авторы EA ON EA.Aid = # TT.Aid

У этого индекса нет поддержки на стороне #TT, и, похоже, он не равен индексу на стороне таблицы авторов.

WHERE EA.Email IS NOT NULL AND EA.Email != ' '  

у него нет вспомогательного индекса, что вызывает сканирование.

Там гораздо больше проблем, с появлением значительного числа сортировок, которые, вероятно, исчезнут с подходящими индексами - вам придется разобраться с некоторыми базовыми индексами таблиц, а затем получить новый план / набор запросов проблем и итеративно исправьте план - вы не исправите его одним выстрелом «серебряной пули».

1 голос
/ 07 октября 2009

Вам нужна помощь в написании запроса или помощь в исправлении производительности? Сам запрос должен быть относительно простым. Это не то место, где вы получите максимальную отдачу от своих денег.

SQL Server поставляется с инструментами для анализа запросов и повышения производительности путем настройки индексов. Вот где вы увидите самую большую помощь в быстром запуске.

0 голосов
/ 07 октября 2009

Учитывая вышеупомянутые условия Это запрос, который я создал, но он занимает 3 минуты (так много времени для ответа веб-страницы):

CREATE PROC [dbo].[GetAuthorForMailing]
(
    @classNumber INT,
    @noPapers int,
    @year int,
    @percent int
)
AS
BEGIN

CREATE TABLE #TT
(
    Aid bigint, 
    allPapers int,
    classPapers int,    
    perc as CEILING(CAST(classPapers AS DECIMAL) / CAST(allPapers AS DECIMAL) * 100)
)
INSERT INTO #TT(Aid,allPapers,classPapers)
SELECT [YearAuthors].Aid,   
            (
             SELECT COUNT(EA.Aid) 
             FROM Authors EA
             WHERE EA.Aid =[YearAuthors].Aid) AS [AllPapers],
            (
             SELECT COUNT(*) 
             FROM Articles ED INNER JOIN Authors EAD ON EAD.ArId = ED.ArId
             WHERE EAD.Aid = [YearAuthors].Aid AND ED.ClassNumber = @classNumber) AS [ClassPapers]

FROM
(
        SELECT DISTINCT Aid
        FROM Authors EAE
        WHERE EAE.[Year] >= @year AND EAE.Email IS NOT NULL AND EAE.Email != ' '

)AS [YearAuthors]

SELECT DISTINCT EA.Aid,EA.Surname,EA.Email,[Year]
FROM #TT INNER JOIN Authors EA ON EA.Aid = #TT.Aid  
    AND allPapers > @noPapers 
    AND perc > @percent
    AND EA.[Year] = (SELECT MAX([Year]) FROM Authors WHERE Aid = EA.Aid)
WHERE EA.Email IS NOT NULL AND EA.Email != ' '
DROP TABLE #TT
0 голосов
/ 07 октября 2009

Первым шагом будет соответствующие индексы . Так как критерии «где» являются основными претендентами, а затем элементы, не используемые в «где», но выбранные, могут быть просто включены в индекс. Как уже упоминалось, есть стандартные инструменты и запросы, чтобы найти их.

Чтобы сосредоточиться на запросе, выполняемом запрос, включив «Запрос | Включить план выполнения » (Ctrl + M). Это должно показать любые очевидные узкие места.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...