Как уменьшить время ответа простого запроса на выборку? - PullRequest
3 голосов
/ 19 ноября 2010

MarketPlane таблица содержит более 60 миллионов строк.

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

SELECT COUNT(primaryKeyColumn) 
FROM   MarketPlan 
WHERE  LaunchDate > @date

Я реализовал все вещи, упомянутые в ваших ссылках, даже сейчас я реализовал With(nolock), которые уменьшают время ответа до 5 минут.

Ответы [ 10 ]

3 голосов
/ 19 ноября 2010
0 голосов
/ 22 ноября 2011

Есть два способа сделать это

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

    * 1006. *
  2. Вы можете попробовать использовать горизонтальное разбиение, это повлияет на ваш существующий дизайн таблицы, но это самый оптимальный способ сделать это, посмотрите это http://blog.sqlauthority.com/2008/01/25/sql-server-2005-database-table-partitioning-tutorial-how-to-horizontal-partition-database-table/

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

Насколько широкий стол?Если таблица широкая (т. Е. Много столбцов (n) char, (n) varchar или xml), может быть значительное количество операций ввода-вывода, в результате чего запрос будет выполняться медленно в результате использования кластеризованного индекса.

Чтобы определить, вызывает ли IO длительное время запроса, выполните следующие действия:

  1. Создайте некластеризованный индекс только для столбца LaunchDate.
  2. Запустите приведенный ниже запрос, который считает LaunchDate и принудительно использует новый индекс.

    SELECT COUNT (LaunchDate)

    FROM MarketPlan WITH (INDEX = TheNewIndexName)

    ГДЕ LaunchDate> @ date

Мне не нравится использовать индексные подсказки, и я предлагаю этот совет только для того, чтобы доказать, вызывает ли IO длительное время запроса.

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

Самое простое, что вы можете сделать, это:

SELECT COUNT(LaunchDate) 
FROM   MarketPlan 
WHERE  LaunchDate > @date

Это гарантирует вам поиск только по индексу для любого индекса LaunchDate.

Также (это зависит от вашего плана выполнения), явидел случаи (но не специфичные для SQL Server), в которых> выполнял сканирование таблицы, а BETWEEN использовал индекс.Если вы знаете верхнюю дату, вы можете попробовать WHERE LaunchDate BETWEEN @date AND <<Literal Date>>.

0 голосов

"ГДЕ LaunchDate> @date"

Является ли значение параметра @date, определенное в том же пакете (или транзакцией, или контекстом)?
Если нет, то это будетпривести к сканированию кластеризованного индекса (всех строк) вместо поиска кластерного индекса (просто строк, удовлетворяющих условию WHERE), если его значение поступает извне текущего пакета (как, например, входной параметр хранимой процедуры или функции udf).
Запрос не может быть полностью оптимизирован оптимизатором SQL Server (во время компиляции), что приводит к полному сканированию таблицы, поскольку значение параметра известно только во время выполнения

Обновление: комментарий к ответам с предложением OLAP.
OLAP - это просто концепция, кубы SSAS - это только один из возможных способов реализации OLAP.
Это удобство, а не обязательство при получении / использовании концепции OLAP.
Вы не использовали SSAS для использования концепции OLAP.
См., Например, Имитация OLAP

Обновление 2: комментарий к вопросу в комментариях к ответу :

MDX - это опция / удобство / функция / функциональность, предоставляемая SSAS (кубы / OLAP), а не обязательство

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

Создайте новый индекс, как этот:

CREATE INDEX xLaunchDate на MarketPlan (LaunchDate, primaryKeyColumn)

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

http://blog.sqlauthority.com/2009/10/08/sql-server-query-optimization-remove-bookmark-lookup-remove-rid-lookup-remove-key-lookup-part-2/

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

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

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

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

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

Предполагается, что SQL-Server основан на @date, хотя то же самое можно применить к большинству баз данных.

Если вашим основным запросом является выбор диапазона данных (на основе выборки), добавление или изменение CLUSTERED INEDX значительно улучшат время запроса.

См .: http://msdn.microsoft.com/en-us/library/ms190639.aspx

По умолчанию SQL-Server создает первичный ключ в качестве кластерного индекса, что прекрасно с точки зрения транзакций, но если вы сосредоточены на извлечении данных, то изменение этого значения по умолчанию имеет огромное значение.

CREATE CLUSTERED INDEX name ON MarketPlan (LaunchDate DESC)

Примечание. Предполагается, что LaunchDate является значением статической даты и в основном вставляется в возрастающем / последовательном порядке для минимизации фрагментации индекса.

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

Имеет ли указанная таблица индекс для столбца LaunchDate? Кроме того, вы действительно хотели опубликовать LaunchDate>@date?

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