[MDEV-6115] window functions as in the SQL standard Created: 2014-04-15 Updated: 2019-03-04 Resolved: 2019-03-04 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Optimizer - Window functions |
| Fix Version/s: | 10.2.2 |
| Type: | Task | Priority: | Major |
| Reporter: | Sergei Golubchik | Assignee: | Igor Babaev |
| Resolution: | Fixed | Votes: | 17 |
| Labels: | optimizer | ||
| Issue Links: |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Description |
Spec draftPlace in the optimizerWindow functions are evaluated on the result set after the WHERE, GROUP BY and HAVING have been applied.
Basic idea about operationLet's start with one window function:
Window function is evaluated for each row of the result set. It is a function of row's partition, we need to look at the rows of the resultset that are ordered according to order_expr. $window_spec specifies at which rows we need to look. Sometimes it's certain preceding rows, sometimes it's certain following rows (and sometimes it's both?) Execution can be done as follows:
Unresolved questions:
Multiple window functionsA query may use multiple window functions which use different PARTITION BY / ORDER BY expressions:
The query should be evaluated as follows:
Links
|
| Comments |
| Comment by tmjee [ 2014-09-10 ] | |||||||||||||||||||
|
Hi guys, Any ideas if this will make it into 10.2.0 and also roughly when is the release date for 10.2.0? Cheers | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2014-09-10 ] | |||||||||||||||||||
|
Currently, target_version= "10.2" for this task means "not 10.1". At the moment, there are no specific plans for 10.2, and nobody has committed to getting this feature done for 10.2. Thanks for showing your interest (tasks that people are interested in are more likely to be done). | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2015-05-04 ] | |||||||||||||||||||
|
A subset of Windowing Functions is being worked on in | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2015-10-15 ] | |||||||||||||||||||
|
There is a tree for this feature, https://github.com/MariaDB/server/tree/bb-10.1-mdev6115 | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2015-11-26 ] | |||||||||||||||||||
|
Notes from the discussion: it looks like | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2015-11-26 ] | |||||||||||||||||||
|
| |||||||||||||||||||
| Comment by Michael Widenius [ 2016-02-02 ] | |||||||||||||||||||
|
Here follows a simple approach to implement windowing functions without having to touch much code in sql_select.cc. Almost all code is in Items with some refactoring of init_read_record() so that we can have several filesorts open for the same table. During parsing, create window function (WF) items and put them also in a
The above works for avergage, sum, count etc. Benefits of the above solution:
| |||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-02-03 ] | |||||||||||||||||||
|
cvicentiu 's current code is in https://github.com/MariaDB/server/tree/10.2-window_simple . Note that the branch was rebased on 10.2 (so ORIGINAL WINDOW FUNCS commits were modified) The first thing that doesn't work is: temp.table is created but it doesn't have fields for window function values. | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-02-03 ] | |||||||||||||||||||
|
Ok, window functions do not get into the temp.table because they are skipped here:
create_tmp_field has this switch:
and Item::WINDOW_FUNC_ITEM ends up right in the default:. | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-02-03 ] | |||||||||||||||||||
|
Another thing to research: | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-02-03 ] | |||||||||||||||||||
|
Ok this patch makes the temporary table to create fields for window functions:
However, the temp.table field for "row_number() over (partition by a)" is of | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-02-04 ] | |||||||||||||||||||
|
Looking at whether the > Temporary tables created will automaticly store values used by WF functions and place to hold the WF result itself. part of the spec is satisfied. When I try this query:
the temporary table has fields:
OK. However, when I try this:
the temporary table only has:
This is incorrect. | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-02-04 ] | |||||||||||||||||||
|
Questions that need to be resolved: == sort_order construction == == PARTITION BY group detection == 2. filesort result actually consists of { sort_key= {parititon_sort_key, orderby_sort_key}, rowid} pairs (right?) We could compare the sort_key parts. The problem is being able to tell where the partition_sort_key ends (we need to compare partition_sort_key only). Are they variable-length or they always have the same length? | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-02-04 ] | |||||||||||||||||||
|
Discovered a bug in the current code: st_select_lex::window_specs is not cleaned up across queries. If you run queries with window functions repeatedly, you will eventually fail this assert:
Which also raises a question: are window functions counted when computing the upper bound for ref_pointer_array_size? (And will this question be relevant after | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-02-04 ] | |||||||||||||||||||
|
Ok the problem with temp.table not having all required fields is gone after I fixed the bug mentioned in the previous comment.
field[1] corresponds to Item_func_plus. | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-02-04 ] | |||||||||||||||||||
Nope. Tried a small example (too small to require merges), and filesort() called save_index() to produce an array with result data. It seems it wrote only rowids there.
This part won't have been a problem. Look at filesort()'s sort_order parameter. SORT_FIELD::length is the length of mem-comparable form (i.e. it is a constant). For NULL-able expressions one needs to add a NULL-byte. We can't use sort keys produced by filesort, but perhaps we could re-use filesort's approach to producing them.. We have the filled SORT_FIELD structure... | |||||||||||||||||||
| Comment by Igor Babaev [ 2016-02-05 ] | |||||||||||||||||||
|
Sergey, create_sort_index() creates a special index. After it has been created you can read records one by one in the order that you passed as a parameter to create_sort_index(). The records are read with a special read function. | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-02-06 ] | |||||||||||||||||||
|
Filed | |||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-02-25 ] | |||||||||||||||||||
|
My recollection of the discussion on the last call: 1. High-level and low-level cursors
2. De-couple cursor movement from action
3. Use of row numbers for partition bound detection.Igor> it is possible to use row number to tell when partition bound ends.
onle of these cursors is always ahead of the other two. The idea is:
| |||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-03-02 ] | |||||||||||||||||||
|
Take-aways from yesterday discussion CursorsIt seems like the latest cursors are a step in the right direction. Need to continue Window frame exclusion
(Btw, PostgreSQL doesn't support frame exclusion). Further tasksSergeiP
Vicentiu
Igor
| |||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-03-02 ] | |||||||||||||||||||
|
Filed |