2015-12-22 3 views
0

У меня есть следующий студенческий стол:PostgreSQL выбирая самые высокие значения

Student_Name Student_RollNo Student_Marks1 Student_Marks2 
Andrew  10    90.9   9.2 
Blake  2    78.2   100 
Fisher  1    69.2   89 
Alex   1    98.8   82.1 

Мой запрос:

select * 
from Student 
order by (Student_Marks1+Student_Marks2) limit 1; 

т.е. я хочу, чтобы получить студенческие детали студента с самыми высокими отметками. Здесь высшие метки - это функция, которая является суммированием Student_Marks1 и Student_Marks2. Теперь мне любопытно узнать, какой алгоритм использует postgresql (или mysql) для выполнения этого рейтинга?

i.e postgresql применять ORDER BY сначала, а затем LIMIT; ИЛИ применяется сначала LIMIT, а затем ORDER BY; или использует алгоритм, который применяет ORDER BY и LIMIT вместе

+0

натуральный заказ, от низкого до максимально высокий. Если столбца с числовым типом, затем сортируется на основе числового значения. Если текстовый столбец, отсортированный на основе сортировки набора символов, используется для столбца (по существу, в алфавитном порядке). Если вы хотите самый большой первый, то порядок убывания: 'order by Student_Marks desc' – DBug

+0

@DBug Да, вы очень правы, но что делать, если я хочу заказать на основе нескольких атрибутов (или столбцов). Тогда мне любопытно узнать, какой алгоритм ранжирования использует postgresql для выполнения этого рейтинга –

+0

Вы спрашиваете, как работает ORDER BY? –

ответ

1

В общем случае алгоритм очень прост:
1. Retireve строка из таблицы Student
2. Сортировка всех результирующего от # 1, используя ORDER BY выражения
3. Нанесите пункт LIMIT (+ смещение), чтобы получить порцию строк из упорядоченных результирующих, полученного из # 2

Вы можете прочитать на LIMIT здесь: http://www.postgresql.org/docs/9.4/static/queries-limit.html


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


Вы можете изучить, как эта работа рассматривает планы объяснения.
Пусть говорят, что это индекс, созданный на этой таблице:

create index student_mark1 on student(student_marks1); 

Этот запрос дает следующий объяснить план:

select * From student 
order by student_marks2 
limit 1; 

Limit (cost=5.06..5.06 rows=1 width=178) (actual time=0.088..0.089 rows=1 loops=1) 
    Output: student_name, student_rollno, student_marks1, student_marks2 
    -> Sort (cost=5.06..5.57 rows=204 width=178) (actual time=0.088..0.088 rows=1 loops=1) 
     Output: student_name, student_rollno, student_marks1, student_marks2 
     Sort Key: student.student_marks2 
     Sort Method: top-N heapsort Memory: 25kB 
     -> Seq Scan on public.student (cost=0.00..4.04 rows=204 width=178) (actual time=0.007..0.021 rows=204 loops=1) 
       Output: student_name, student_rollno, student_marks1, student_marks2 

Вы должны прочитать этот план от основания до до
Первая операция Seq scan - это означает, что все строки считываются с диска (вся таблица - см. actual rows = 204).
Затем выполняется операция сортировки (ORDER BY).
И последняя операция LIMIT 1 (в верхней части плана)


Сравните выше план по этому запросу:

select * From student 
order by student_marks1 
limit 1; 

Limit (cost=0.14..0.24 rows=1 width=178) (actual time=0.010..0.010 rows=1 loops=1) 
    Output: student_name, student_rollno, student_marks1, student_marks2 
    -> Index Scan using student_mark1 on public.student (cost=0.14..19.20 rows=204 width=178) (actual time=0.009..0.009 rows=1 loops=1) 
     Output: student_name, student_rollno, student_marks1, student_marks2 

Здесь сортировочная фаза пропускается, так как мы можем использовать индекс для извлечения строк в требуемом порядке (ORDER BY student_marks1 => INDEX ON Student(student_marks1)).
Пожалуйста, обратите внимание на Actual rows = 1 в самой нижней операции: «Индексная проверка».
Это означает, что PostgreSQL не сканирует весь индекс, а извлекает только 1 (первую) строку из индекса, потому что он знает, чем запрос имеет предложение LIMIT 1. (Иногда иногда говорят, что PostgreSQL «подтолкнуло» предложение limit 1 к операции сканирования индекса и использовало его для уменьшения количества отсканированных записей в индексе).


Дополнительную информацию об использовании индексов для ускорения ORDER BY вы можете найти здесь: http://www.postgresql.org/docs/8.3/static/indexes-ordering.html


В случае, если запрос на ваш вопрос, то ORDER BY clasue содержит выражение Student_Marks1+Student_Marks2, а не просто столбцы. Объяснить план для этого запроса выглядит следующим образом:

select * 
From student 
order by student_marks1 + student_marks2 
limit 2; 

Limit (cost=7.10..7.11 rows=2 width=178) (actual time=0.207..0.207 rows=2 loops=1) 
    Output: student_name, student_rollno, student_marks1, student_marks2, (((student_marks1)::numeric + student_marks2)) 
    -> Sort (cost=7.10..7.61 rows=204 width=178) (actual time=0.205..0.205 rows=2 loops=1) 
     Output: student_name, student_rollno, student_marks1, student_marks2, (((student_marks1)::numeric + student_marks2)) 
     Sort Key: (((student.student_marks1)::numeric + student.student_marks2)) 
     Sort Method: top-N heapsort Memory: 25kB 
     -> Seq Scan on public.student (cost=0.00..5.06 rows=204 width=178) (actual time=0.019..0.107 rows=204 loops=1) 
       Output: student_name, student_rollno, student_marks1, student_marks2, ((student_marks1)::numeric + student_marks2) 

Но вы можете ускорить этот запрос создавая function based index, таким способом:

create index student_mark12 on student((student_marks1 + student_marks2)); 

После создания индекса, мы имеем теперь:

Limit (cost=0.14..0.34 rows=2 width=178) (actual time=0.044..0.047 rows=2 loops=1) 
    Output: student_name, student_rollno, student_marks1, student_marks2, (((student_marks1)::numeric + student_marks2)) 
    -> Index Scan using student_mark12 on public.student (cost=0.14..20.22 rows=204 width=178) (actual time=0.043..0.046 rows=2 loops=1) 
     Output: student_name, student_rollno, student_marks1, student_marks2, ((student_marks1)::numeric + student_marks2) 

Обратите внимание, что Postgre использует индекс в данном случае, и извлекает только две записи из него (фактических строк = 2) в соответствии с пунктом LIMIT 2.

1

PostgreSQL использует стандартный операторный класс B-tree для определения порядка сортировки в выражении ORDER BY (по умолчанию используется ASC по умолчанию с использованием <, с использованием DESC, использующего > чтобы увеличить).

Что касается вашего комментария о нескольких атрибутах, он использует ORDER BY в последовательности, основанной на вашей записи полей сортировки.

+0

Я боюсь ... но как она использует ORDER BY в последовательности на 2 атрибута, т.е. mark1 и marks2. Поскольку он должен сортировать по суммированию меток 1 и меток2, а затем использовать лимит, то есть получить самую высокую запись –

+0

Также вы можете обратиться ко мне в какой-то документ, из которого я могу больше узнать об этом. –

Смежные вопросы