SQL "ORDER BY" медленность

Правда ли, что ORDER BY в целом довольно медленный? Я пытаюсь запустить несколько операторов sql, где предложение WHERE довольно просто, но затем я пытаюсь ORDER BY в индексированном столбце VARCHAR(50).

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

На этом этапе я ищу либо

  • оптимизировать SQL-запрос
  • сортировать результирующий набор в коде

Вот фактический запрос, который я пытаюсь запустить:

// B.SYNTAX is a TEXT/CLOB field
// Indexes on NAME, MODULENAME. PREVIOUS is a CHAR(1) with no index
"SELECT A.NAME, B.SYNTAX, B.DESCRIPTION, A.RATE1, A.RATE2, 
A.RATE3, A.STARTDATE, A.ENDDATE, A.HIDE, A.CATEGORYNAME 
FROM A, B WHERE A.MODULENAME='"+loadedModuleName+"' 
AND A.NAME = B.NAME AND (A.PREVIOUS<>'N' OR A.PREVIOUS IS NULL) 
ORDER BY A.NAME"

Размер таблицы A составляет ~ 2000 строк, а B около ~ 500.

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

Я ожидаю, что будут возвращены сотни записей (менее 1000).

Что бы вы сделали? Любые советы приветствуются. Спасибо.

Ответ 1

Я провел некоторое тестирование производительности прошлой ночью в более производственной базе данных (а не в разработке), и вот что я нашел:

Всего строк в таблице A: 13000

Всего строк в таблице B: 5000

Строки, возвращаемые запросом соединения: 5000

Время, затрачиваемое при использовании с предложением ORDER BY: ~ 5.422 секунды

Время, если не используется предложение ORDER BY: ~ 5.345 секунд.

Итак, похоже, что ORDER BY не имеет большого значения. (Я согласен с добавлением нескольких миллисекунд).

Я также тестировал, установив для всех значений B.SYNTAX значение NULL, чтобы убедиться, что это была не просто латентность сети при передаче большого количества данных.

Теперь я удалил B.SYNTAX из предложения SELECT, и запрос занял всего 0,8 секунды!

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

Спасибо всем, кто ответил. Я узнал совсем немного, и это заставило меня попробовать несколько разных вещей.

Ответ 2

Заказ по индексированному полю не должен быть медленным, так как он может вытащить данные в порядке индекса. Возможно, вы захотите разместить информацию о структуре базы данных (DDL) и фактическом запросе, чтобы люди могли взглянуть.

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

UPDATE: Хорошо, несколько вещей. Во-первых, вы не должны использовать конструкцию "+ loadedModuleName +", поскольку она делает каждый запрос уникальным и закручивает оптимизатор. Используйте параметр. Во-вторых, предложение Order by неоднозначно относительно того, является ли оно таблицей A или B - сделать это явным и выбрать таблицу с индексом (даже если у обоих есть индексы, сделайте это явным). Наконец, ваше "Предыдущее" поле можно индексировать даже как char (1). Я бы сделал все, кроме последнего предложенного индекса, скорости тестирования и, если все еще медленно, перейдите к индексу и снова проверьте.

ОБНОВЛЕНИЕ. Таким образом, вы будете возвращать < 1000 записей, но каков размер общей таблицы?

ОБНОВЛЕНИЕ О, мужик, извините, я этого раньше не понимал. Если вы хотите развернуть его правильно на SQL Server, ваш запрос должен быть:

SELECT A.NAME, B.SYNTAX, B.DESCRIPTION, A.RATE1, A.RATE2, A.RATE3, A.STARTDATE, A.ENDDATE, A.HIDE, A.CATEGORYNAME 
FROM Table1 A join Table2 B on (A.Name=B.Name)
WHERE ([email protected]) AND (A.PREVIOUS<>'N' OR A.PREVIOUS IS NULL) 
ORDER BY A.NAME

Попробуйте это, и я почти гарантирую, что вы увидите огромное ускорение.

Ответ 3

ORDER BY обычно неактивен, если база данных может найти индекс, соответствующий выражению ORDER BY.

Однако ваш оператор SQL может включать в себя другие вещи, которые заставляют базу данных сканировать всю таблицу перед возвратом результатов, например SELECT TOP n

Ответ 4

Если ваш фильтр выглядит так:

WHERE col1 = @value1
      AND col2 = @value2
      AND col3 = @value3
ORDER BY
      col4

вам нужно создать индекс на (col1, col2, col3, col4).

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

Если у вас нет такого индекса, произойдет одно из следующих событий:

  • Оптимизатор будет использовать индекс для фильтрации по условию WHERE, но он все равно должен иметь ORDER оставшиеся строки.
  • Оптимизатор будет использовать индекс для ORDER значений, но все значения должны быть рассмотрены, чтобы отфильтровать их.
  • Оптимизатор не будет использовать индекс вообще, поэтому оба минуса из 2 "ВСЕ-значения должны быть рассмотрены, чтобы отфильтровать их", и 1 "все остальные строки должны быть упорядочены" - это правда.

Ответ 5

ОБНОВЛЕНИЕ. В качестве запроса, который вы опубликовали, я думаю, что лучший вариант - считать запрос хорошим, потому что:

  • Для нескольких строк не заботятся о том, кто выполняет эту работу. Тогда вам будет легче использовать ORDER BY.
  • Для большого количества строк не оставляйте работу клиента: RDMBS более специализирован и уверен, что у сервера больше памяти и процессора.

Советы для заказов, которые вы должны учитывать:

  • ORDER BY - это ТОЛЬКО способ получения гарантии на SQL-запрос.
  • Работник лучший при сортировке - это база данных в любом случае: УБЕДИТЕСЬ НА ЭТОМ!
  • Попробуйте минимизировать мощность для возвращенных строк.
  • Создание индексов по запросу. Это означает, что упорядоченные столбцы сохраняются в индексе.
  • Избегайте индексирования, если запрос выполняется быстро.
  • Вы можете считать, что индексы отсортированы, а если вы сортируете только таблицу и имеете хорошие индексы, сортировка может стоить около нуля.

Для получения дополнительных эмпирических указаний найдите этот другой вопрос SO.

Ответ 6

Это не должно быть медленным. Оптимизируйте свой запрос и структуру базы данных (по крайней мере, индексы и статистические данные, если это SQL Server). Может быть, в вашем запросе есть еще что-то, кроме ORDER BY, которое вызывает эту медленность?

SELECT A.NAME, B.SYNTAX, B.DESCRIPTION, A.RATE1, A.RATE2, A.RATE3,
       A.STARTDATE, A.ENDDATE, A.HIDE, A.CATEGORYNAME
FROM Table1 A JOIN Table2 B on A.Name = B.Name
WHERE A.MODULENAME = @ModuleName AND A.PREVIOUS<>'N' OR A.PREVIOUS IS NULL
ORDER BY A.NAME

Вариант 1

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

// if your query looks like this:
SELECT [Name], [Title], [Count] ORDER BY [COUNT]

// you can create an index on [Name], [Title], [Count]

Вариант 3

Создайте view и привяжите его к schema. Затем запросите данные из этого view.

Вариант 3

Если вы используете SQL Server 2005 и выше, вы также можете попробовать выполнить запрос в Профилире SQL Server, и он порекомендует вам лучший индекс и статистику, которые вы можете применить к своей таблице в чтобы оптимизировать эту конкретную производительность запросов.

Вариант 4

Попробуйте перестроить индексы и статистику.

Вариант 5

Вы можете попробовать разместить индекс/таблицу в отдельной файловой группе на другом жестком диске.

Ответ 7

Если вы выберете несколько достаточно строк для отображения, неясно, что в предложении ORDER BY будет какое-либо заметное количество времени, если вы не ограничиваете количество строк, возвращаемых с помощью LIMIT или TOP.

Нам нужна дополнительная информация. Какие dbms? Как выглядит план запроса? Вы просматривали планы запросов с помощью и без ORDER BY? Какие различия вы видите?


EDIT:

SELECT A.NAME, B.SYNTAX, B.DESCRIPTION, A.RATE1, A.RATE2,  
A.RATE3, A.STARTDATE, A.ENDDATE, A.HIDE, A.CATEGORYNAME  
FROM A, B  
WHERE A.MODULENAME='"+loadedModuleName+"'   
  AND A.NAME = B.NAME  
  AND (A.PREVIOUS<>'N' OR A.PREVIOUS IS NULL)  
ORDER BY NAME

Является ли NAME primary key? Есть ли index на NAME? Само по себе или с другими полями? В какой последовательности?
Сколько строк возвращается для одного загруженногоModuleName?
Я подозреваю, что медленность происходит от "A.PREVIOUS <> 'N' OR A.PREVIOUS IS NULL" Попробуйте использовать (NOT A.PREVIOUS = 'N'), который, я думаю, эквивалентен и может немного помочь.
Введите запрос с и без ORDER BY и посмотрите, не отличается ли время. Это не должно быть.


EDIT:

Если NAME не является уникальным ни в A, ни в B, ваше соединение будет частично баллистическим, если каждый экземпляр A.NAME перекрестится на B.NAME. Если совпадение 50 строк и 50 строк B совпадают, вы получите 2500 строк результатов, которые могут быть не такими, какие вы планируете.

Ответ 8

ORDER BY не особенно медленный, особенно если в этом столбце есть индекс. В частности, если у вас есть кластерный индекс в этом столбце, данные уже отсортированы.

Вы также можете использовать подкачки (TOP или ROW_NUMBER) и т.д., чтобы помочь.

Ответ 9

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

Добавление ORDER BY заставит его ждать в базе данных для всех результатов, что покажет реальную скорость запроса.

В этих случаях исходный запрос и ORDERed имеют одинаковую скорость; вы были просто обмануты, думая, что первый из них был быстрым, потому что ваш редактор быстро получил 50 или около того строк.

Ответ 10

Нельзя сказать, что "порядок" медленнее и само по себе. У вас много RDBM, чтобы рассмотреть их собственную реализацию, а также тип данных и схему индексирования. Тем не менее я сомневаюсь, что вы можете сортировать его быстрее на стороне клиента, чем на сервере, но это не значит, что сортировка на сервере - это правильная вещь.

Ответ 11

Здесь есть много проблем.

С точки зрения чистой производительности и предположения, что индексы правильно настроены, базы данных очень хороши при сортировке. Для одного запроса по отдельности сортировка в базе данных, вероятно, самая быстрая.

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

С другой стороны, здесь более важно рассмотреть, чем чистую производительность. Вы также хотите подумать о будущем обслуживании. Что более удобно, чем простой пункт "ORDER BY"? Это только одна строка кода, по сравнению с тем, кто знает, сколько дополнительного программиста работает, чтобы получить вид, работающий в другом месте. Это может быть случай, когда вам лучше бросить деньги на проблему, чтобы убедиться, что ваша база данных просто способна поддерживать приемлемый уровень производительности, сортировки и все такое.

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

Ответ 12

ORDER BY заставляет RDBMS сортировать.

Для сортировки требуются ресурсы, которые могут отсутствовать на сервере RDBMS.

В некоторых случаях (например, запросы с одной таблицей) вы можете написать ORDER BY, который соответствует индексам, и если ваша RDBMS гарантирует, что таблицы хранятся в индексном порядке, это может быть нулевая стоимость. [Конструкция БД, которая зависит от множества запросов с одной таблицей, может быть еще больше улучшена путем отбрасывания СУРБД и использования файлов.]

Как правило, ORDER BY придется сортировать.

"Я полагал, что получение базы данных для этого для меня является наиболее эффективным".

Это допущение ошибочно. База данных не обязательно более эффективна, чем ваша программа за пределами базы данных.

Ответ 13

Сортировка на клиенте, на мой взгляд, вы не должны делать. Механизмы базы данных оптимизированы для сортировки данных.

Как и другие, если вы можете ограничить количество выбранных строк, это будет работать быстрее.

Ответ на следующие вопросы может помочь в дальнейшем:

  • Сколько строк возвращается запрос?
  • Сколько столбцов выбрано?
  • Вы присоединяетесь к любым таблицам?
  • Сколько времени занимает/без ORDER BY?

Ответ 14

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

Какую базу данных вы используете? Как кто-то, кто тратит массу времени на MySQL, вещь, которая выпрыгивает на меня, является оператором OR. MySQL может быть действительно глупым с ORs. Я видел, что быстрее сделать два выбора и СОЕДИНИТЬ их вместе.

Если количество строк велико (в таблице, а не возвращено), это может быть фактором.

В противном случае я согласен с другими сообщениями. Индексы должны делать это быстро, и часто лучше позволить БД делать это, а не обрабатывать его самостоятельно. БД знает, что он делает. Если у вас нет ДЕЙСТВИТЕЛЬНО большого набора данных и вы хотите переложить нагрузку на сортировку на клиента (так что БД может принимать больше запросов), я бы позволил БД выполнять сортировку.