Требуется помощь в запросе SQL

Ниже приведен мой SQL-запрос, который выполняется для 30000000 строк, и для его выполнения требуется 6 минут, индексы определяются для всех столбцов, используемых в предложении where, как wll как внутреннее соединение. Пожалуйста, помогите мне.

SELECT auditData.id,nstmp.ProviderMaster_ID as CDRComment,Auditdata.Calltypetag  
from    Auditdata AuditData
inner join NoSeriesMaster_temp nstmp  on nstmp.NosereisTemp like '91%'
where  Auditdata.id in (select id from auditdata_temp1 where tatcalltype is  null)  
    and AuditData.CallTolen=12 and  Auditdata.Callto like nstmp.NosereisTemp + '%' and       AuditData.AuditMaster_ID=74

заранее спасибо


person John    schedule 28.07.2009    source источник
comment
Вы используете MS SQL Server? Не могли бы вы опубликовать план выполнения?   -  person Justin    schedule 28.07.2009


Ответы (5)


Подзапрос

Сначала избавьтесь от подзапроса и используйте вместо этого соединение, например:

SELECT 
auditData.id, nstmp.ProviderMaster_ID as CDRComment, Auditdata.Calltypetag  

FROM Auditdata AuditData

INNER JOIN NoSeriesMaster_temp nstmp  
ON Auditdata.Callto like nstmp.NosereisTemp + '%' 
AND nstmp.NosereisTemp like '91%'

INNER JOIN auditdata_temp1 adt
ON Auditdata.id = adt.id
AND adt.tatcalltype is  null

WHERE AuditData.CallTolen = 12
AND AuditData.AuditMaster_ID = 74

Это немного поможет.

Соединение с использованием предложения Like

  1. Это испортит ваш план выполнения, поскольку оптимизатор не сможет вычислить лучший путь поиска, поскольку значение изменяется во время выполнения.
  2. Это текстовый поиск, который будет оцениваться для каждой строки AuditData ... не очень хорошо!

Решение

Добавьте битовый столбец в NoSeriesMaster и обновите его по расписанию для не обновленных записей до 1, где NosereisTemp, например, «91%». Вместо этого используйте это битовое значение в своем запросе.

Посмотрите, как это изменить:

Auditdata.Callto like nstmp.NosereisTemp + '%' 

Используя аналогичную концепцию. Трудно сказать, как именно, не зная своих данных.

person badbod99    schedule 28.07.2009

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

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

Другое решение может заключаться в разделении большой таблицы на срезы или агрегировании данных с использованием некоторых методов OLAP.

Какое ядро ​​СУБД вы используете?

person HyLian    schedule 28.07.2009
comment
этот комментарий должен быть в мета, но я больше не хочу использовать мета или предлагать улучшения для SO (плохой опыт с голосованием против). причина для комментария - спрашивающий пометил это как sql и server, и я почти уверен, что имелся в виду sql-server. В любом случае, какой смысл иметь серверный тег. Теги не должны полностью определяться пользователем. Полностью избежать вопроса о том, какой компонент Database Engine вы используете. - person Liao; 28.07.2009
comment
в настоящее время я использую SQL Server 2000 - person John; 28.07.2009
comment
[не по теме]: Согласен, Ляо, поменял теги ... [/ вне темы] - person RuudKok; 28.07.2009

У вас есть LIKE выражения как в предложении WHERE (like nstmp.NosereisTemp + '%'), так и в предложении JOIN ON (например, «91%»). Это всегда будет медленнее, чем использование прямого сравнения, и я думаю, что это также может повлиять на то, могут ли ваши индексы использоваться эффективно.

Можно ли было бы изменить таблицы, включив в них поле, которое можно было бы использовать для присоединения / фильтрации? Например, не могли бы вы предварительно вычислить like '91%' и сохранить значение в таблице?

person Gary McGill    schedule 28.07.2009

В лучшем случае он будет выполнять сканирование индекса, когда вы выполняете проверку условий LIKE (не сможет выполнять поиск по индексу, что обычно лучше для производительности). С этим мало что можно сделать - просто проверьте план выполнения, следите за сканированием таблиц, на которое нужно будет смотреть (отсутствует индекс)

Возможно, изменение предложения Auditdata.id IN на условие EXISTS может работать лучше (я предполагаю, что id - это PK в auditdata_temp1, и поэтому не будет нескольких с одинаковым значением, и в этом случае EXISTS не сделает огромная разница, если таковая есть).

Имея такой объем данных, вы можете захотеть рассмотреть возможность разделения своих данных, что вы можете сделать, начиная с SQL 2005, но вам нужна Enterprise Edition, поэтому это может быть не вариант. Дополнительную информацию см. здесь.

Покрывающие индексы - может быть, вы получите лучшую производительность с одним.

На самом деле нам нужно увидеть план выполнения, который может повлиять на другие вещи.

person AdaTheDev    schedule 28.07.2009

Вам следует немного сместить критерии JOIN ON / WHERE, критерии соединения должны быть предикатом, который связывает две таблицы:

INNER JOIN NoSeriesMaster_temp nstmp
ON Auditdata.Callto like nstmp.NosereisTemp + '%

Затем вам нужно переместить следующий предикат в раздел WHERE вашего запроса:

WHERE nstmp.NosereisTemp like '91%'

Это может помочь SQL-серверу разработать более разумный план выполнения.

Если это не помогает, вам следует изучить возможность предварительного расчета значения nstmp.NosereisTemp like '91%' - SQL Server должен отлично обрабатывать запросы такого типа, однако это может повлиять на JOINS.

Более того, без плана выполнения невозможно сказать, однако я могу точно сказать, что это НЕ ваш подзапрос! :-) (Не стесняйтесь попробовать переписать его как JOIN, однако я буду очень удивлен, если удаление подзапроса - это то, что решит вашу проблему)

person Justin    schedule 28.07.2009