Allow packed keys and packed values of non-sorted fields in the sort buffer
(MDEV-6915)
|
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Optimizer |
| Affects Version/s: | None |
| Fix Version/s: | 10.5.2 |
| Type: | Technical task | Priority: | Major |
| Reporter: | Varun Gupta (Inactive) | Assignee: | Varun Gupta (Inactive) |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | None | ||
| Issue Links: |
|
||||||||||||||||||||||||||||||||||||||||||||
| Description |
|
This task in a part of EDIT: this is the spec of what got implemented: Contents:1. Background 1. BackgroundBefore this MDEV, filesort() sorted the data using mem-comparable keys. That is, if we wanted to sort by
then the filesort code would for each row generate one "Sort Key" and then sort the rows by their Sort Keys. The Sort Keys are mem-comparable (that is, are compared by memcmp()) and they are fixed size: the sort key has the same length regardless of what value it represents. This causes inefficient memory usage. 1.1 Implementation detailsfilesort.cc: make_sortkey() is the function that produces a sort key from a record. The function treats Field and Item objects differently. class Field has
sort_string produces mem-comparable image of the field value for each datatype. make_sort_key is a non-virtual function which handles encoding of SQL null values. For Items, Type_handler has a virtual function:
which various datatypes overload. 1.1.1 Why fields and items are treated differentlyMy (Sergey P) guess is as follows: if we use fields we get more compact sort keys. For example:
Q1 uses a Field. It's a Field_int, so the sort key is 4 bytes long. 2. Solution : Packed Sort KeysNote that one can have mem-comparable keys are that are not fixed-size. MyRocks uses such encoding for example. However for this MDEV it was decided to store the original (non-mem-comparable) values instead, and use a datatype-aware key comparison function. (See the issue comments for the reasoning) 2.1 Packed key formatThe keys are stored in a new variable-size data format called "packed". The format is as follows:
sort_key_length is the length of the whole key.
null_byte is present if the field/item is NULLable. The format of the packed_value depends on the datatype. For "non-packable" datatypes it is just their mem-comparable form, as before. The "packable" datatypes are currently variable-length strings and the packed format for them is (for binary blobs, see a note below):
2.2 Which format to useThe advantage of Packed Key Format is potential space savings for variable-length fields.
Currently the logic is: use Packed Key Format if we would save 20 or more bytes when constructing a sort key from values that have empty string for each packable component. 3. Special cases3.1 Handling very long stringsBefore this MDEV, the size of sort key was limited by @@max_sort_length variable.
3.2 Handling for long binary stringsLong binary strings receive special treatment. A sort key for the long binary string is truncated at max_sort_length bytes like described above, but then a "suffix" is appended which contains the total length of the value before the truncation. 3.3 Handling very long strings with Packed sort keysTruncating multi-byte string at N bytes is not safe because one can cut in the middle of a character. This combination of circumstances:
is deemed to be relatively rare so it was decided to just use the non-packed sort keys in this case. 4. Sort key columns in addon_fieldsCurrently, each sort key column is actually stored twice |
| Comments |
| Comment by Varun Gupta (Inactive) [ 2020-01-28 ] | ||||||||||||||||||||||||||||||||||||||||
ImplementationFor each record the sort key would look like
For fixed lengths there is no need to store length, but they will be packed too if the value IS NULL (same as packed addon fields) A new compare function needs to be added that would compare two dynamic length sort keys and return the comparison accordingly. | ||||||||||||||||||||||||||||||||||||||||
| Comment by Varun Gupta (Inactive) [ 2020-01-28 ] | ||||||||||||||||||||||||||||||||||||||||
Structure to hold SORT ITEMS Currently done in SORT_FIELD, we may need to add additional parameters
max_sort_length [user controllable variable]The number of bytes to use when sorting data values. The server uses only the first max_sort_length bytes of each value and ignores the rest Range: [2^2, 2^22] For VARCHAR and CHAR length bytes of 1 and 2 would be fine New compare function to compare sort keys In the new compare function we need to take into account the dynamic nature of the sort keys due to packing. | ||||||||||||||||||||||||||||||||||||||||
| Comment by Varun Gupta (Inactive) [ 2020-02-04 ] | ||||||||||||||||||||||||||||||||||||||||
|
A suggestion made by psergey was that we could have the format for sort keys as:
Here we store the null byte along with the field. | ||||||||||||||||||||||||||||||||||||||||
| Comment by Varun Gupta (Inactive) [ 2020-02-05 ] | ||||||||||||||||||||||||||||||||||||||||
|
Here are some discussion points which I had with bar He still suggests to store original values, reasons: In case on Unicode collation algorithm, original values use much less spaces than their keys.
when using packed sort-keys: compare function is strnncollsp() | ||||||||||||||||||||||||||||||||||||||||
| Comment by Varun Gupta (Inactive) [ 2020-02-16 ] | ||||||||||||||||||||||||||||||||||||||||
|
The branch where the code is rebased on 10.5 is 10.5-mdev6915-ext Also the patch can be found here: | ||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2020-02-21 ] | ||||||||||||||||||||||||||||||||||||||||
|
It turns out this code changes the comparison function even for fixed-size I'm debugging this example:
and on stock 10.5 I see
That is, sorting uses memcmp for key comparison:
Debugging the same example on this patch I see it is using
| ||||||||||||||||||||||||||||||||||||||||
| Comment by Varun Gupta (Inactive) [ 2020-03-03 ] | ||||||||||||||||||||||||||||||||||||||||
|
The latest tree is 10.5-mdev6915-ext | ||||||||||||||||||||||||||||||||||||||||
| Comment by Igor Babaev [ 2020-03-04 ] | ||||||||||||||||||||||||||||||||||||||||
|
Varun, | ||||||||||||||||||||||||||||||||||||||||
| Comment by Varun Gupta (Inactive) [ 2020-03-04 ] | ||||||||||||||||||||||||||||||||||||||||
|
Ans1 : In 10.4 we use the strxfrm form (mem-comparable sort keys are formed), so weights can be cut at any byte as the mem-comparable form ensure that each byte would be such that the ordering is maintained between 2 keys. Ans2 : It should be not hard to remove sorted fields from addon fields, but we need to make sure that all entire value is in the sort_field, that is there is not truncation or cutting (because of max_sort_length) | ||||||||||||||||||||||||||||||||||||||||
| Comment by Igor Babaev [ 2020-03-04 ] | ||||||||||||||||||||||||||||||||||||||||
|
Varun,
For the above test case: | ||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2020-03-05 ] | ||||||||||||||||||||||||||||||||||||||||
|
This is not reproducible with the current code. | ||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2020-03-10 ] | ||||||||||||||||||||||||||||||||||||||||
|
The latest patch is Ok to push. | ||||||||||||||||||||||||||||||||||||||||
| Comment by Varun Gupta (Inactive) [ 2020-03-10 ] | ||||||||||||||||||||||||||||||||||||||||
|
Pushed to 10.5
|