postgresql 选择最高值
postgresql selecting highest values
我有以下学生table:
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)使用哪种算法来执行此排名?
即 postgresql 是否先应用 ORDER BY,然后应用 LIMIT;还是先应用 LIMIT,然后再应用 ORDER BY;或者它是否使用同时应用 ORDER BY 和 LIMIT 的算法
PostgreSQL 使用默认的 B 树运算符 class 来确定 ORDER BY 表达式中的排序顺序(ASC 默认使用 < 对较小的进行排序,DESC 使用 > 进行较大的排序)。
至于你的评论问题关于多个属性,它根据你输入的排序字段顺序使用ORDER BY。
总的来说算法很简单:
- 从
Student
table 中检索行
- 使用 ORDER BY 表达式对 #1 中的整个结果集进行排序
- 应用 LIMIT 子句(+ 偏移量)从 #2
获得的有序结果集中获取部分行
您可以在此处阅读有关 LIMIT 的更多信息:http://www.postgresql.org/docs/9.4/static/queries-limit.html
在某些情况下,在 ORDER BY 操作(排序)期间会考虑 LIMIT 以加快查询速度,尤其是当可以使用某些索引来消除排序操作时。
您可以查看解释计划来检查这项工作。
假设在此 table:
上创建了一个索引
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
- 这意味着从磁盘读取所有行(整个table - 参见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
:`Index scan'。
这意味着,PostgreSQL 不会扫描整个索引,而是只从索引中检索 1(第一)行,因为它知道查询有 LIMIT 1 子句。 (有时有人说 PostgreSQL 将 limit 1 子句“下推”到索引扫描操作中,并用它来减少索引中扫描的条目数)。
有关使用索引加速 ORDER BY 的更多信息,您可以在此处找到:http://www.postgresql.org/docs/8.3/static/indexes-ordering.html
如果您的问题中的查询,ORDER BY
子句包含一个表达式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 在这种情况下使用索引,并根据 LIMIT 2
子句从中仅检索 2 个条目(实际行数 = 2)。
我有以下学生table:
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)使用哪种算法来执行此排名?
即 postgresql 是否先应用 ORDER BY,然后应用 LIMIT;还是先应用 LIMIT,然后再应用 ORDER BY;或者它是否使用同时应用 ORDER BY 和 LIMIT 的算法
PostgreSQL 使用默认的 B 树运算符 class 来确定 ORDER BY 表达式中的排序顺序(ASC 默认使用 < 对较小的进行排序,DESC 使用 > 进行较大的排序)。
至于你的评论问题关于多个属性,它根据你输入的排序字段顺序使用ORDER BY。
总的来说算法很简单:
- 从
Student
table 中检索行
- 使用 ORDER BY 表达式对 #1 中的整个结果集进行排序
- 应用 LIMIT 子句(+ 偏移量)从 #2 获得的有序结果集中获取部分行
您可以在此处阅读有关 LIMIT 的更多信息:http://www.postgresql.org/docs/9.4/static/queries-limit.html
在某些情况下,在 ORDER BY 操作(排序)期间会考虑 LIMIT 以加快查询速度,尤其是当可以使用某些索引来消除排序操作时。
您可以查看解释计划来检查这项工作。
假设在此 table:
上创建了一个索引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
- 这意味着从磁盘读取所有行(整个table - 参见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
:`Index scan'。
这意味着,PostgreSQL 不会扫描整个索引,而是只从索引中检索 1(第一)行,因为它知道查询有 LIMIT 1 子句。 (有时有人说 PostgreSQL 将 limit 1 子句“下推”到索引扫描操作中,并用它来减少索引中扫描的条目数)。
有关使用索引加速 ORDER BY 的更多信息,您可以在此处找到:http://www.postgresql.org/docs/8.3/static/indexes-ordering.html
如果您的问题中的查询,ORDER BY
子句包含一个表达式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 在这种情况下使用索引,并根据 LIMIT 2
子句从中仅检索 2 个条目(实际行数 = 2)。