SQL Server 2005 - Присоединение не прекращается - Скорость проблемы? - PullRequest
0 голосов
/ 13 декабря 2010

Кто-нибудь знает, почему эта операция соединения не завершается:

SELECT * FROM
(SELECT LOWER([Computer Name]) AS 'cname' FROM table1)
AS export,
(SELECT AssetID AS 'CCID', Hostname AS 'cname' FROM table2 WHERE LastVersionFlag=1)
AS known

WHERE export.cname = LEFT(known.cname, LEN(export.cname));

Проблема, которую я хочу решить:

  • Столбец таблицы "cname" содержит: "pc1"
  • Столбец таблицы 2 "hostname" содержит: "pc1.domain.com"
  • Таблица2 также содержит столбец «CCID»: 123123

В результате запроса мне нужно получить CCID каждого "cname" из таблицы 1.

EDIT:

Запрос выполняется в течение> 15 минут и не производит ни вывода, ни завершения.

  • В таблице 1 содержится около 100 000 строк
  • Таблица2 содержит около 200.000ров

Есть идеи, как ускорить запрос?!

EDIT2:

Индексы помещаются в Table1 cname и Table2 cname

Расписание задач выглядит следующим образом: http://i55.tinypic.com/1z3o0t4.png

Ответы [ 4 ]

1 голос
/ 13 декабря 2010

Объединение всех предложений даст вам следующий запрос.
При правильном индексировании и количестве упоминаний, которые вы упомянули, для возврата результатов не потребуется минут.

SELECT  cname = t1.[Computer Name] 
        , CCID = k.AssetID
        , Hostname = k.cname
FROM    table1 t1
        INNER JOIN known k ON k.Hostname LIKE t1.[Computer Name]  + '%'
WHERE   k.LastVersionFlag = 1        
1 голос
/ 13 декабря 2010

Мне кажется, ваш запрос не выполняется из-за размера данных.

Требуется сгенерировать декартово произведение из 100.000 * 200.000 строк, а затем применить условия WHERE.

Сравнение SQL Server нечувствительно к регистру, если для сопоставления столбца задано нечувствительное к регистру (по умолчанию используется сопоставление базы данных и сервера).

Чтобы ускорить операцию объединения, добавьте (уникальные?) Индексы для таблиц 1. [Имя компьютера] и table2.Hostname.

Измените ваш запрос на

SELECT known.CCID, export.[Computer Name] AS cname 
FROM table1 AS export
INNER JOIN table2 AS known 
    ON known.Hostname LIKE export.[Computer Name] + '%' 
    AND LastVersionFlag=1 

Если все ваши имена хостов используют точечную нотацию cname, используйте '.%'.

1 голос
/ 13 декабря 2010

Примечание: SQL Server по умолчанию работает в нечувствительном к регистру режиме (если вы не вносили никаких изменений), поэтому вам не нужно заботиться о верхнем / нижнем регистре. Использование таких функций, как LOWER, предотвращает использование индексов.

И чтобы ускорить последний WHERE, вы можете переписать его с LIKE, который будет использовать индекс по задействованным столбцам (если он у вас есть). Это было бы что-то вроде (как в ответе Девио): ​​

known.cname LIKE (export.cname + '%')
1 голос
/ 13 декабря 2010

Это то, что вы ищете, базовое соединение?

SELECT known.CCID, export.[Computer Name] AS cname 
FROM
table1 AS export
INNER JOIN table2 AS known ON LOWER(export.[Computer Name]) = LOWER(LEFT(known.cname, LEN(export.[Computer Name])))
WHERE LastVersionFlag=1 

Редактировать: Вот несколько советов по ускорению запроса:

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

например, ...ON known.cname = export.[Computed Column] collate SQL_Latin1_General_Cp437_CI_AS_KI_WI

Ваш лучший шаг - создать постоянный вычисляемый столбец в таблице 2, который просто содержит имя cname, используя вашу формулу из объединения LEFT(known.cname, LEN(export.[Computer Name])), затем вы можете поместить индексна вычисляемом столбце, а также столбце cname таблицы1.Когда вы закончите, ваше объединение будет простым равенством, а не сравнением, которое сильно манипулирует.Это позволит обработчику запросов составить более оптимизированный план.

...