❖ The Sort Operation |
Sorting is explicit in queries only in the order by
select * from Students order by name;
Sorting is used internally in other operations:
group by
For large data on disks, need external sorts such as merge sort.
❖ Two-way Merge Sort (cont) |
Requires at least three in-memory buffers:
Assumption: cost of Merge operation on two in-memory buffers ≅ 0.
❖ Comparison for Sorting |
Above assumes that we have a function to compare tuples.
Needs to understand ordering on different data types.
Need a function tupCompare(r1,r2,f)
strcmp
int tupCompare(r1,r2,f) { if (r1.f < r2.f) return -1; if (r1.f > r2.f) return 1; return 0; }
Assume =, <, > are available for all attribute types.
❖ Comparison for Sorting (cont) |
In reality, need to sort on multiple attributes and ASC/DESC, e.g.
-- example multi-attribute sort
select * from Students
order by age desc, year_enrolled
Sketch of multi-attribute sorting function
int tupCompare(r1,r2,criteria) { foreach (f,ord) in criteria { if (ord == ASC) { if (r1.f < r2.f) return -1; if (r1.f > r2.f) return 1; } else { if (r1.f > r2.f) return -1; if (r1.f < r2.f) return 1; } } return 0; }
❖ Cost of Two-way Merge Sort |
For a file containing b data pages:
Example: Relation with r=105 and c=50 ⇒ b=2000 pages.
Number of passes for sort: ceil(log22000) = 11
Reads/writes entire file 11 times! Can we do better?
❖ n-Way Merge Sort |
Initial pass uses: B total buffers
Reads B pages at a time, sorts in memory, writes out in order
❖ n-Way Merge Sort (cont) |
Method:
// Produce B-page-long runs for each group of B pages in Rel { read B pages into memory buffers sort group in memory write B pages out to Temp } // Merge runs until everything sorted numberOfRuns = ceil(b/B) while (numberOfRuns > 1) { // n-way merge, where n=B-1 for each group of n runs in Temp { merge into a single run via input buffers write run to newTemp via output buffer } numberOfRuns = ceil(numberOfRuns/n) Temp = newTemp // swap input/output files }
❖ Cost of n-Way Merge Sort |
Consider file where b = 4096, B = 16 total buffers:
❖ Cost of n-Way Merge Sort (cont) |
Generalising from previous example ...
For b data pages and B buffers
❖ Sorting in PostgreSQL |
Sort uses a merge-sort (from Knuth) similar to above:
SortTuple
qsort()
If memory fills while reading, form "runs" and do disk-based sort.
❖ Sorting in PostgreSQL (cont) |
Disk-based sort has phases:
workMem
Implementation of "tapes": backend/utils/sort/logtape.c
❖ Sorting in PostgreSQL (cont) |
Sorting comparison operators are obtained via catalog (in Type.o
// gets pointer to function via pg_operator struct Tuplesortstate { ... SortTupleComparator ... }; // returns negative, zero, positive ApplySortComparator(Datum datum1, bool isnull1, Datum datum2, bool isnull2, SortSupport sort_helper);
Flags in SortSupport
ApplySortComparator()
tupCompare()
Produced: 1 Mar 2021