Гарантирует ли заказ в соответствии с порядком выбора? - PullRequest
11 голосов
/ 02 сентября 2011

У меня есть представление, для которого имеет смысл использовать только определенный порядок. Я хотел бы включить в представление предложение ORDER BY, чтобы все SELECT в этом представлении могли его опустить. Тем не менее, я обеспокоен тем, что заказ не обязательно переносится на SELECT, поскольку в нем не указан заказ.

Существует ли случай, когда упорядочение, указанное в представлении, не будет отражено в результатах выбора в этом представлении (кроме предложения order by в представлении)?

Ответы [ 3 ]

8 голосов
/ 02 сентября 2011

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

Это потому, чтоОптимизатор запросов может получить доступ к строкам различными способами в зависимости от запроса, статистики таблиц, количества строк, индексов и т. д.Если он знает, что в вашем запросе нет предложения ORDER BY, он может игнорировать порядок строк в порядке (кашель), чтобы быстрее возвращать строки.

Немного не по теме.,.

Порядок сортировки не обязательно одинаков для разных платформ, даже для известных сопоставлений.Я понимаю, что сортировка UTF-8 в Mac OS X особенно странная.(Разработчики PostgreSQL называют это broken .) PostgreSQL полагается на strcoll (), который, как я понимаю, зависит от локали ОС.

Мне не ясно, как PostgreSQL 9.1 справится с этим.В 9.1, вы можете иметь несколько индексов, каждый с разным сопоставлением .ORDER BY, который не определяет параметры сортировки, обычно использует параметры сортировки столбцов базовой таблицы, но что оптимизатор будет делать с index , который определяет параметры сортировки, отличные от неиндексированного столбца в базовой таблице

1 голос
/ 03 сентября 2011

Не вижу ответа.Просто добавив мой ответ здесь.

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

Это потому, что PostgreSQL переписываетВаш запрос объединяется в представлении.

CREATE VIEW v AS SELECT * FROM people ORDER BY surname;
-- next two are identical
SELECT * FROM v WHERE forename='Fred';
SELECT * FROM people WHERE forename='Fred' ORDER BY surname;

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

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

0 голосов
/ 02 сентября 2011

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

Но ради наблюдений учтите следующее:

  1. SELECT * FROM (select * from foo order by bar) foobar;
    

    Запрос должен вернуть заказано .

  2. SELECT * FROM vw_foo; -- where vw_foo is the sub-select above
    

    Запрос должен вернуть заказанный .

  3. SELECT * FROM vw_foo LEFT JOIN (select * from bar) bar ON vw_foo.id = bar.id;
    

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

Отказ от ответственности:

Как и @Catcall, вы никогда не должны зависеть от какой-либо неявной сортировки, так как много раз она будет оставлена ​​на усмотрение движка базы данных. Базы данных рассчитаны на скорость и надежность; они часто взаимодействуют с памятью и пытаются вытащить / протолкнуть данные как можно быстрее. Однако упорядочение не основано исключительно на управлении памятью , есть несколько факторов, которые участвуют.

Если вы не имеете в виду что-то конкретное, вам следует выполнить сортировку в конце (по внешнему запросу).


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

SELECT * 
FORM   (select   trunc(random()*999999+1) as i 
        from     generate_series(1,1000000) 
        order by i
       ) foo;

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

...