Вопрос

Я унаследовал новую систему и пытаюсь сделать некоторые улучшения в данных. Я пытаюсь улучшить этот стол и не могу понять свои выводы.

У меня есть следующая структура таблицы:

CREATE TABLE [dbo].[Calls](
    [CallID] [varchar](8) NOT NULL PRIMARY KEY,
    [RecvdDate] [varchar](10) NOT NULL,
    [yr] [int] NOT NULL,
    [Mnth] [int] NOT NULL,
    [CallStatus] [varchar](50) NOT NULL,
    [Category] [varchar](100) NOT NULL,
    [QCall] [varchar](15) NOT NULL,
    [KOUNT] [int] NOT NULL)

Эта таблица имеет около 220к записей в нем. Мне нужно вернуть все записи, которые имеют дату превышения конкретной даты. В этом случае 12/1/2009. Этот запрос вернет около 66K записей, и требуется около 4 секунд. Из прошлых систем я работал над этим кажется высоким. Особенно учитывая, как мало записей в таблице. Поэтому я хотел бы принести это время вниз.

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

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

Любая помощь ценится.

Редактировать: вот запрос, который я пытаюсь запустить и проверить скорость таблицы. Я обычно выпускаю колонны, но только для простоты, которые я использовал *:

SELECT *
FROM _FirstSlaLevel_Tickets_New
WHERE TicketRecvdDateTime >= '12/01/2009'

РЕДАКТИРОВАТЬ 2: Поэтому я упомянул, что пытался создать таблицу с столбцом даты, в котором содержались данные Recvddate, но в качестве даты, а не варчар. Это то, что находится в столбце TicketRecvDateTime в приведенном выше запросе. Оригинальный запрос, который я использую против этой таблицы:

SELECT *
FROM Calls
WHERE CAST(RecvdDate AS DATE) >= '12/01/2009'
Это было полезно?

Решение

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

В вашем примере это кажется вероятным, поскольку у вас исполняется 1/4 количества строк в базе данных. Ниже приведена хорошая статья, которая объясняет это: http://www.sqlskills.com/BLOGS/KIMBERLY/category/The-Tipping-Point.aspx

Другие советы

SELECT * обычно придает плохой производительности.

Либо индекс будет проигнорирован, либо вы получите поиск ключей/закладки в кластерный индекс. Неважно: оба могут работать плохо.

Например, если у вас был этот запрос, и индекс на TickeTrecVdDateTime Включен Callstatus, то это, скорее всего, будет работать, как ожидалось. Это было бы покрытие

SELECT CallStatus
FROM _FirstSlaLevel_Tickets_New
WHERE TicketRecvdDateTime >= '12/01/2009'

Это в дополнение к ответу Рэнди Миндера: поиск ключей/закладки может быть достаточно дешевым для нескольких рядов, но не для большой части данных таблицы.

Ваш запрос быстрее с указателем (или, более точно, является одинаковой скоростью W / или W / O индекс), потому что и индекс на RecvdDate будем всегда игнорироваться в выражении, как CAST(RecvdDate AS DATE) >= '12/01/2009'. Анкет Это необычайное выражение, поскольку это требует, чтобы столбец был преобразован через функцию функции. Для этого индекса событие, которое нужно рассмотреть, вы должны выразить свои критерии фильтра точно на столбец, который индексируется, а не на выражении, основанном на нем. Это был бы первый шаг.

Есть еще шаги:

  • Избавьтесь от столбца VARCHAR (10) для дат и замените его на соответствующую дату или столбец DateTime. Хранение даты и/или времени в качестве строк пронизаны проблемами. Не только для индексации, но и для правильности.
  • Таблица, которая часто отсканирована на диапазоне на основе колонны (поскольку большинство таких таблиц журнала вызовов есть), должны быть сгруппированы этим столбцом.
  • Очень маловероятно, что вам действительно нужно yr и mnth колонны Если они вам действительно нужны, то, вероятно, они вам нужны в качестве вычисленных столбцов.

.

CREATE TABLE [dbo].[Calls](
    [CallID] [varchar](8) NOT NULL,
    [RecvdDate] [datetime](10) NOT NULL,
    [CallStatus] [varchar](50) NOT NULL,
    [Category] [varchar](100) NOT NULL,
    [QCall] [varchar](15) NOT NULL,
    [KOUNT] [int] NOT NULL,
    CONSTRAINT [PK_Calls_CallId] PRIMARY KEY NONCLUSTERED ([CallID]));

CREATE CLUSTERED INDEX cdxCalls ON Calls(RecvDate);

SELECT *
FROM Calls
WHERE RecvDate >= '12/01/2009';

Конечно, правильная структура таблицы и индексов должна быть результатом тщательного анализа, учитывая все вовлеченные факторы, включая производительность обновления, другие запросы и т. Д. Я рекомендую вам начать с того, что проходите все темы, включенные в Проектирование индексов.

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

Вы можете создать индекс на TicketRecvdDateTime, но вы не можете избежать переломного момента, что @randy Minder обсуждает. Однако сканирование на меньшем индексе (меньше, чем сканирование таблицы), вернет бы меньше страниц.

Предполагая, что Recvddate - это TicketRecvDateTime, о котором вы говорите:

SQL Server сравнивает только даты в одиночных цитатах, если тип поля является датой. Ваш запрос, вероятно, сравнивает их как varchar. Попробуйте добавить ряд на 999/99/0001 и посмотрите, показывает ли он внизу.

Если так, то результаты вашего запроса неверны. Изменить тип на сегодняшний день.

Обратите внимание, что varchar не работает хорошо, dateTime делает.

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

РЕДАКТИРОВАНИЕ: На провидящем редактировании CAST / DATETIME, позвольте мне указать, что анализ даты от Varchar является очень дорогой операцией. Вы делаете это 220К раз. Это убьет производительность.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top