Почему этот оператор Sql (с двумя объединениями таблиц) занимает 5 минут? - PullRequest
5 голосов
/ 16 ноября 2010

Обновления: 3 обновления добавлены ниже

Следующий оператор sql занимает 5 минут.Я просто.Не.Получить.Она :( В первой таблице 6861534 строки. В второй таблице немного меньше .. а в третьей таблице (которая содержит 4 ГЕОГРАФИЧЕСКИХ ПОЛЯ) то же самое, что и в первой.

Эти GEOGRAPHY поля в3-я таблица ... они не должны связываться с оператором sql ... не так ли? Может ли это быть из-за того, что таблица настолько велика (из-за полей GEOGRAPHY), что имеет огромные размеры страниц или что-то в этом роде ...уничтожить сканирование таблицы COUNT?

SELECT COUNT(*)
FROM [dbo].[Locations] a
    inner join [dbo].[MyUSALocations] b on a.LocationId = b.LocationId
    inner join [dbo].[GeographyBoundaries] c on a.locationid = c.LocationId

alt text

alt text

alt text

alt text

Обновление

По запросу, вот еще некоторая информация о таблице GeographyBoundaries ... alt text

/****** Object:  Index [PK_GeographyBoundaries]    Script Date: 11/16/2010 12:42:36 ******/
ALTER TABLE [dbo].[GeographyBoundaries] ADD  CONSTRAINT [PK_GeographyBoundaries] PRIMARY KEY CLUSTERED 
(
    [LocationId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

Обновление № 2 - после добавления некластеризованного индекса

После добавления некластеризованного индекса он теперь упал до 4 секунд! Что удивительно. Но почему ?

alt text

What Zee Frak?

Обновление 3 - еще более интересная и запутанная информация!

Теперь, когда я просто ОДНО присоединяюсь и форсирую INDEX .. ят восходит к 5 минутам.Я сделал это с

  • Убедитесь, что таблица MyUSALocations не связывает вещи с Joins.
  • Убедитесь, что ПК делает странные вещи.

.

SELECT COUNT(*)
FROM [dbo].[Locations] a 
        INNER JOIN [dbo].[GeographyBoundaries] c
            WITH (INDEX(PK_GeographyBoundaries)) ON a.locationid = c.LocationId

Ответы [ 4 ]

4 голосов
/ 16 ноября 2010

Это не правильно.

У меня есть две возможности:

1) Статистика в таблицах устарела.Перестройте индексы и обновите статистику.

2) Как вы сказали, записи таблицы Geography занимают много страниц (не одна запись, охватывающая несколько страниц, поскольку она не может, но запись близка к отметке 8K).В этом случае, как ни странно, может помочь создание другого некластеризованного индекса в кластеризованном индексе.

ОБНОВЛЕНИЕ

Я рад, что это сработало.Теперь некоторые пояснения.

Прежде всего, если что-то не так и план выполнения выглядит странно, всегда смотрит на статистику и перестраивает индексы.

Создание некластеризованного индекса для кластеризованного индексаобычно это не должно приносить никакой пользы, но если в таблице много записей, а запись близка к пределу в 8 КБ, это полезно.Как вы знаете, SQL, когда он идет на диск, чтобы загрузить запись, он загружает страницу 8K.Аналогичным образом, при переходе на индексы он загрузит страницу 8K.Теперь, когда индекс представляет собой 4-байтовое целое число, это означает загрузку идентификатора для 2000 записей, в то время как он собирается загружать несколько записей, если он использует кластерный индекс (имейте в виду, что все, что нам нужно, это идентификатор для бита JOIN).Теперь, когда это бинарный поиск, я не ожидаю, что он сильно поможет.Так что, возможно, что-то еще не совсем правильно, но трудно догадаться, не увидев систему.

0 голосов
/ 16 ноября 2010

Что ж, вам не нужно включать таблицу "местоположения", прямое соединение между USA_Loacations и географическими границами будет иметь значение.Оптимизатор уже заметил это и разобрал таблицу расстановок, но может выбрать лучшую стратегию объединения, если вы присоединитесь к ним напрямую.

0 голосов
/ 16 ноября 2010

Я бы сказал, что большая часть работы - это ввод-вывод.План запроса, по-видимому, указывает на высокую стоимость ввода-вывода относительно стоимости процессора.Например, в PK_GeographyBoundries предполагаемая стоимость ЦП составляет около 7,5, а предполагаемая стоимость ввода-вывода - около 1730, что составляет большой процент от предполагаемой стоимости оператора.

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

Если важно повысить производительность, то вам нужно искать способы ускорения физического ввода-вывода.

Я не уверен, что столбцы географиивлияют на производительность.План запроса показывает, что размеры строк малы (по 11 байт).

0 голосов
/ 16 ноября 2010

Не знаю наверняка, не увидев некоторые данные, но 97% ваших затрат приходится на сканирование кластерного индекса в таблице GeographyBonudaries. Является ли LocationID основным ключом вашей таблицы GeographyBoundaries?

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

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

Просто из любопытства, каково определение ваших PK_GeographyBoundaries?

...