Повышение производительности запросов SQL Server 2005 - PullRequest
3 голосов
/ 15 июня 2010

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

http://76.12.87.164/cpd/testperformance.cfm

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

Я не использую хранимые процедуры - запросы встроены в Coldfusion.

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

Спасибо

Ответы [ 5 ]

2 голосов
/ 15 июня 2010

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

  • Если столбец имеет только одно или два уникальных значения (каноническим примером этого является «пол» - с возможными значениями только «Мужской» и «Женский», здесь нет никакого индекса для индекса). Как правило, вам нужен индекс, который сможет ограничивать строки, которые должны быть обработаны значительным числом (например, индекс, который только уменьшает пространство поиска на 50%, не стоит того, но индекс, который уменьшает его на 99 % - это ).
  • Если вы ищете x LIKE '%something', то индекс не имеет смысла. Если вы считаете индекс указанием определенного порядка для строк, то сортировка по x, если вы ищете "% что-то", бесполезна: вам все равно придется сканировать все строки .

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

SELECT
  *
FROM (
  SELECT TOP 10
    ROW_NUMBER() OVER (ORDER BY sq.name) AS Row,
    sq.*
  FROM (
    SELECT
      c.*,
      p.providername,
      p.school,
      p.website,
      p.type
    FROM
      cpd_COURSES c, cpd_PROVIDERS p
    WHERE
      c.providerid = p.providerid AND
      c.activatedYN = 'Y' AND
      (
        c.name like '%accounting%' OR
        c.title like '%accounting%' OR
        c.keywords like '%accounting%'
      )
  ) sq
) AS temp
WHERE
  Row >= 1 AND Row <= 10 

В этом случае я буду считать, что cpd_COURSES.providerid является внешним ключом для cpd_PROVIDERS.providerid, и в этом случае вам не нужен индекс, потому что он уже будет иметь его.

Кроме того, столбец activatedYN является столбцом T / F и (согласно моему правилу выше об ограничении возможных значений только на 50%) столбец T / F также не должен индексироваться.

Наконец, поскольку при поиске по запросу x LIKE '%accounting%' вам не нужен индекс по имени, названию или ключевым словам - потому что он никогда не будет использоваться.

Итак, главное, что вам нужно сделать в этом случае, это убедиться, что cpd_COURSES.providerid на самом деле является внешним ключом для cpd_PROVIDERS.providerid.

SQL Server Specific

Поскольку вы используете SQL Server, в Management Studio есть ряд инструментов, которые помогут вам решить, куда вам нужно поместить индексы. Если вы используете «Index Tuning Wizard», он обычно довольно хорошо говорит вам, что даст вам хорошие улучшения производительности. Вы просто вставляете в него свой запрос, и он вернется с рекомендациями по добавлению индексов.

Вам все равно нужно быть немного осторожнее с добавляемыми вами индексами, потому что чем больше у вас индексов, тем медленнее будут INSERT s и UPDATE s. Поэтому иногда вам необходимо объединять индексы или просто игнорировать их, если они не дают достаточного выигрыша в производительности. Некоторое суждение требуется.

1 голос
/ 15 июня 2010

Это реальные данные базы данных?Говоря условно, 52 000 записей - это очень маленькая таблица, для которой SQL 2005 может иметь дело.

Интересно, сколько ОЗУ выделено серверу SQL или на каком диске находится база данных.Жесткий диск IDE или даже SATA не может дать такую ​​же производительность, как SAS-диск со скоростью 15K RPM, и было бы неплохо, если бы было достаточно оперативной памяти для кэширования большого объема часто используемых данных.

Сказав всея считаю, что предложение "(c.name как"% accounting% "ИЛИ c.title как"% accounting% "ИЛИ c.keywords как"% accounting% ') "проблематично.

Не могли бы высоздайте отдельную таблицу Course_Keywords с двумя столбцами "courseid" и "keyword" (varchar (24) должно быть достаточно для самого длинного ключевого слова?), с составным кластерным индексом для courseid + keyword

Затем, чтобы сделатьПользовательский интерфейс еще более дружественный, используйте AJAX для применения проверки и автозаполнения ключевых слов, когда люди вводят слова в поле ввода ключевых слов.Это дает вам скрытую выгоду от наличия точного ключевого слова для поиска, устраняя необходимость сопоставления с шаблоном с помощью оператора LIKE ...

0 голосов
/ 15 июня 2010

Я бы попробовал изменить ваши операторы IN на запрос EXISTS, чтобы посмотреть, улучшите ли вы производительность при поиске по почтовому индексу.Мой опыт показывает, что операторы IN отлично подходят для небольших списков, но чем они больше, тем выше производительность EXISTS, так как механизм запросов прекратит поиск определенного значения в первом экземпляре, с которым он работает.

<CFIF zipcodes is not "">
    EXISTS (
        SELECT zipcode
        FROM cpd_CODES_ZIPCODES
        WHERE zipcode = p.zipcode
            AND 3963 * (ACOS((SIN(#getzipcodeinfo.latitude#/57.2958) * SIN(latitude/57.2958)) +
            (COS(#getzipcodeinfo.latitude#/57.2958) * COS(latitude/57.2958) *
            COS(longitude/57.2958 - #getzipcodeinfo.longitude#/57.2958)))) <= #radius#
    )
</CFIF>
0 голосов
/ 15 июня 2010

Вы хотите создать индексы для полей, по которым вы ведете поиск.Индекс - это вторичный список ваших записей, отсортированный по индексированным полям.

Подумайте о старомодных печатных желтых страницах - если вы хотите найти человека по фамилии, телефонная книга уже отсортирована втаким образом - Фамилия является полем кластерного индекса.Если вы хотите найти телефонные номера людей по имени Дженнифер или человека с номером телефона 867-5309, вам придется искать каждую запись, и это займет много времени.Если бы сзади был указатель со всеми телефонными номерами или именами, перечисленными по порядку вместе со страницей в телефонной книге, в которой указан этот человек, это было бы намного быстрее.Это будут некластеризованные индексы.

0 голосов
/ 15 июня 2010

Использование CF9? Попробуйте использовать полнотекстовый поиск Solr вместо %xxx%?

...