summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Petrunia <psergey@askmonty.org>2020-03-09 00:29:48 +0300
committerSergei Petrunia <psergey@askmonty.org>2020-03-09 00:29:48 +0300
commitee6c668f24c4e9e49b742b8a2bcaac4ac2298ac0 (patch)
tree8fcb7084de88108ee8e0066b18bbcaa495b517e2
parent0c35e80dc9ff24bcb8e710cb8cb16428c8c9986f (diff)
downloadmariadb-git-10.5-mdev21784-reg1-vfuncs.tar.gz
MDEV-21784: Performance testing for packed sort keys10.5-mdev21784-reg1-vfuncs
A piece of cumulative patch for MDEV-21580 Allow packed sort keys in sort buffer which just adds some virtual functions (without any calls to them)
-rw-r--r--plugin/type_inet/sql_type_inet.cc23
-rw-r--r--plugin/type_inet/sql_type_inet.h3
-rw-r--r--sql/field.cc61
-rw-r--r--sql/field.h27
-rw-r--r--sql/filesort.cc231
-rw-r--r--sql/sql_class.h5
-rw-r--r--sql/sql_type.h45
7 files changed, 394 insertions, 1 deletions
diff --git a/plugin/type_inet/sql_type_inet.cc b/plugin/type_inet/sql_type_inet.cc
index 6803bdba434..a660df053a8 100644
--- a/plugin/type_inet/sql_type_inet.cc
+++ b/plugin/type_inet/sql_type_inet.cc
@@ -1377,6 +1377,29 @@ void Type_handler_inet6::make_sort_key(uchar *to, Item *item,
memcpy(to, tmp.ptr(), tmp.length());
}
+uint
+Type_handler_inet6::make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
+{
+ DBUG_ASSERT(item->type_handler() == this);
+ NativeBufferInet6 tmp;
+ item->val_native_result(current_thd, &tmp);
+ if (item->maybe_null)
+ {
+ if (item->null_value)
+ {
+ *to++=0;
+ return 0;
+ }
+ *to++= 1;
+ }
+ DBUG_ASSERT(!item->null_value);
+ DBUG_ASSERT(Inet6::binary_length() == tmp.length());
+ DBUG_ASSERT(Inet6::binary_length() == sort_field->length);
+ memcpy(to, tmp.ptr(), tmp.length());
+ return tmp.length();
+}
void Type_handler_inet6::sortlength(THD *thd,
const Type_std_attributes *item,
diff --git a/plugin/type_inet/sql_type_inet.h b/plugin/type_inet/sql_type_inet.h
index b483ff94e8d..dd4f530dcf8 100644
--- a/plugin/type_inet/sql_type_inet.h
+++ b/plugin/type_inet/sql_type_inet.h
@@ -516,6 +516,9 @@ public:
void make_sort_key(uchar *to, Item *item,
const SORT_FIELD_ATTR *sort_field, Sort_param *param)
const override;
+ uint make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const override;
diff --git a/sql/field.cc b/sql/field.cc
index 1ce49b0bdfa..62dafd55b57 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1029,6 +1029,61 @@ void Field::make_sort_key(uchar *buff,uint length)
}
+/*
+ @brief
+ Create a packed sort key
+
+ @param buff buffer where values are written
+ @param sort_field sort column structure
+
+ @retval
+ length of the bytes written, does not include the NULL bytes
+*/
+uint
+Field::make_packed_sort_key(uchar *buff, const SORT_FIELD_ATTR *sort_field)
+{
+ if (maybe_null())
+ {
+ if (is_null())
+ {
+ *buff++= 0;
+ return 0; // For NULL values don't write any data
+ }
+ *buff++=1;
+ }
+ sort_string(buff, sort_field->original_length);
+ return sort_field->original_length;
+}
+
+
+uint
+Field_longstr::make_packed_sort_key(uchar *buff,
+ const SORT_FIELD_ATTR *sort_field)
+{
+ if (maybe_null())
+ {
+ if (is_null())
+ {
+ *buff++= 0;
+ return 0; // For NULL values don't write any data
+ }
+ *buff++=1;
+ }
+ uchar *end= pack_sort_string(buff, sort_field);
+ return static_cast<int>(end-buff);
+}
+
+
+uchar*
+Field_longstr::pack_sort_string(uchar *to, const SORT_FIELD_ATTR *sort_field)
+{
+ String buf;
+ val_str(&buf, &buf);
+ return to + sort_field->pack_sort_string(to, buf.lex_cstring(),
+ field_charset());
+}
+
+
/**
@brief
Determine the relative position of the field value in a numeric interval
@@ -8531,6 +8586,12 @@ uint32 Field_blob::sort_length() const
}
+uint32 Field_blob::sort_suffix_length() const
+{
+ return field_charset() == &my_charset_bin ? packlength : 0;
+}
+
+
void Field_blob::sort_string(uchar *to,uint length)
{
String buf;
diff --git a/sql/field.h b/sql/field.h
index 4a8eec35b05..47abae87c1f 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -33,6 +33,7 @@
#include "compat56.h"
#include "sql_type.h" /* Type_std_attributes */
#include "field_comp.h"
+#include "filesort.h"
class Send_field;
class Copy_field;
@@ -1075,6 +1076,12 @@ public:
virtual uint32 data_length() { return pack_length(); }
virtual uint32 sort_length() const { return pack_length(); }
+ /*
+ sort_suffix_length() return the length bytes needed to store the length
+ for binary charset
+ */
+ virtual uint32 sort_suffix_length() const { return 0; }
+
/*
Get the number bytes occupied by the value in the field.
CHAR values are stripped of trailing spaces.
@@ -1410,7 +1417,17 @@ public:
return bytes;
}
+ /*
+ Create mem-comparable sort keys
+ */
void make_sort_key(uchar *buff, uint length);
+
+ /*
+ create a compact sort key which can be compared with a comparison
+ function. They are called packed sort keys
+ */
+ virtual uint make_packed_sort_key(uchar *buff,
+ const SORT_FIELD_ATTR *sort_field);
virtual void make_send_field(Send_field *);
virtual void sort_string(uchar *buff,uint length)=0;
virtual bool optimize_range(uint idx, uint part) const;
@@ -2140,7 +2157,10 @@ public:
bool can_optimize_range(const Item_bool_func *cond,
const Item *item,
bool is_eq_func) const;
- bool is_packable() { return true; }
+ bool is_packable() override { return true; }
+ uint make_packed_sort_key(uchar *buff,
+ const SORT_FIELD_ATTR *sort_field)override;
+ uchar* pack_sort_string(uchar *to, const SORT_FIELD_ATTR *sort_field);
};
/* base class for float and double and decimal (old one) */
@@ -4045,6 +4065,10 @@ public:
return (uint32) field_length + (field_charset() == &my_charset_bin ?
length_bytes : 0);
}
+ virtual uint32 sort_suffix_length() const override
+ {
+ return (field_charset() == &my_charset_bin ? length_bytes : 0);
+ }
Copy_func *get_copy_func(const Field *from) const override;
bool memcpy_field_possible(const Field *from) const override;
void update_data_type_statistics(Data_type_statistics *st) const override
@@ -4353,6 +4377,7 @@ public:
{ return (uint32) (packlength); }
uint row_pack_length() const override { return pack_length_no_ptr(); }
uint32 sort_length() const override;
+ uint32 sort_suffix_length() const override;
uint32 value_length() override { return get_length(); }
virtual uint32 max_data_length() const override
{
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 34fecd516b4..71556a17cc6 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -1177,6 +1177,24 @@ Type_handler_timestamp_common::make_sort_key(uchar *to, Item *item,
void
+Type_handler::store_sort_key_longlong(uchar *to, bool unsigned_flag,
+ longlong value) const
+{
+ to[7]= (uchar) value;
+ to[6]= (uchar) (value >> 8);
+ to[5]= (uchar) (value >> 16);
+ to[4]= (uchar) (value >> 24);
+ to[3]= (uchar) (value >> 32);
+ to[2]= (uchar) (value >> 40);
+ to[1]= (uchar) (value >> 48);
+ if (unsigned_flag) /* Fix sign */
+ to[0]= (uchar) (value >> 56);
+ else
+ to[0]= (uchar) (value >> 56) ^ 128; /* Reverse signbit */
+}
+
+
+void
Type_handler::make_sort_key_longlong(uchar *to,
bool maybe_null,
bool null_value,
@@ -1207,6 +1225,25 @@ Type_handler::make_sort_key_longlong(uchar *to,
}
+uint
+Type_handler::make_packed_sort_key_longlong(uchar *to, bool maybe_null,
+ bool null_value, bool unsigned_flag,
+ longlong value,
+ const SORT_FIELD_ATTR *sort_field) const
+{
+ if (maybe_null)
+ {
+ if (null_value)
+ {
+ *to++= 0;
+ return 0;
+ }
+ *to++= 1;
+ }
+ store_sort_key_longlong(to, unsigned_flag, value);
+ DBUG_ASSERT(sort_field->original_length == sort_field->length);
+ return sort_field->original_length;
+}
void
Type_handler_decimal_result::make_sort_key(uchar *to, Item *item,
const SORT_FIELD_ATTR *sort_field,
@@ -2375,3 +2412,197 @@ SORT_INFO::~SORT_INFO()
free_data();
DBUG_VOID_RETURN;
}
+
+/*
+ TODO varun: add comments here
+*/
+uint
+SORT_FIELD_ATTR::pack_sort_string(uchar *to, const LEX_CSTRING &str,
+ CHARSET_INFO *cs) const
+{
+ DBUG_ASSERT(0);
+ return 0;
+/*
+ uchar *orig_to= to;
+ size_t length, data_length;
+ length= str.length;
+
+ if (length + suffix_length <= original_length)
+ data_length= length;
+ else
+ data_length= original_length - suffix_length;
+
+ // length stored in lowendian form
+ store_lowendian(data_length + suffix_length, to, length_bytes);
+ to+= length_bytes;
+ // copying data length bytes to the buffer
+ memcpy(to, (uchar*)str.str, data_length);
+ to+= data_length;
+
+ if (cs == &my_charset_bin && suffix_length)
+ {
+ // suffix length stored in bigendian form
+ store_bigendian(str.length, to, suffix_length);
+ to+= suffix_length;
+ }
+ return static_cast<uint>(to - orig_to);*/
+}
+uint
+Type_handler_string_result::make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
+{
+ CHARSET_INFO *cs= item->collation.collation;
+ bool maybe_null= item->maybe_null;
+
+ if (maybe_null)
+ *to++= 1;
+
+ String tmp(param->tmp_buffer, param->sort_length, cs);
+ String *res= item->str_result(&tmp);
+ if (!res)
+ {
+ if (maybe_null)
+ {
+ *(to-1)= 0;
+ return 0;
+ }
+ else
+ {
+ /* purecov: begin deadcode */
+ /*
+ This should only happen during extreme conditions if we run out
+ of memory or have an item marked not null when it can be null.
+ This code is here mainly to avoid a hard crash in this case.
+ */
+ DBUG_ASSERT(0);
+ DBUG_PRINT("warning",
+ ("Got null on something that shouldn't be null"));
+ memset(to, 0, sort_field->length); // Avoid crash
+ /* purecov: end */
+ return sort_field->original_length;
+ }
+ }
+ return sort_field->pack_sort_string(to, res->lex_cstring(), cs);
+}
+
+
+uint
+Type_handler_int_result::make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
+{
+ longlong value= item->val_int_result();
+ return make_packed_sort_key_longlong(to, item->maybe_null,
+ item->null_value, item->unsigned_flag,
+ value, sort_field);
+}
+
+
+uint
+Type_handler_decimal_result::make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
+{
+ my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
+ if (item->maybe_null)
+ {
+ if (item->null_value)
+ {
+ *to++=0;
+ return 0;
+ }
+ *to++= 1;
+ }
+ dec_val->to_binary(to, item->max_length - (item->decimals ? 1 : 0),
+ item->decimals);
+ DBUG_ASSERT(sort_field->original_length == sort_field->length);
+ return sort_field->original_length;
+}
+
+
+uint
+Type_handler_real_result::make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
+{
+ double value= item->val_result();
+ if (item->maybe_null)
+ {
+ if (item->null_value)
+ {
+ *to++=0;
+ return 0;
+ }
+ *to++= 1;
+ }
+ change_double_for_sort(value, to);
+ DBUG_ASSERT(sort_field->original_length == sort_field->length);
+ return sort_field->original_length;
+}
+
+
+uint
+Type_handler_temporal_result::make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
+{
+ MYSQL_TIME buf;
+ // This is a temporal type. No nanoseconds. Rounding mode is not important.
+ DBUG_ASSERT(item->cmp_type() == TIME_RESULT);
+ static const Temporal::Options opt(TIME_INVALID_DATES, TIME_FRAC_NONE);
+ if (item->get_date_result(current_thd, &buf, opt))
+ {
+ DBUG_ASSERT(item->maybe_null);
+ DBUG_ASSERT(item->null_value);
+ return make_packed_sort_key_longlong(to, item->maybe_null, true,
+ item->unsigned_flag, 0, sort_field);
+ }
+ return make_packed_sort_key_longlong(to, item->maybe_null, false,
+ item->unsigned_flag, pack_time(&buf),
+ sort_field);
+}
+
+
+uint
+Type_handler_timestamp_common::make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
+{
+ THD *thd= current_thd;
+ uint binlen= my_timestamp_binary_length(item->decimals);
+ Timestamp_or_zero_datetime_native_null native(thd, item);
+ if (native.is_null() || native.is_zero_datetime())
+ {
+ // NULL or '0000-00-00 00:00:00'
+ if (item->maybe_null)
+ {
+ *to++=0;
+ return 0;
+ }
+ else
+ {
+ bzero(to, binlen);
+ return binlen;
+ }
+ }
+ else
+ {
+ if (item->maybe_null)
+ *to++= 1;
+ if (native.length() != binlen)
+ {
+ /*
+ Some items can return native representation with a different
+ number of fractional digits, e.g.: GREATEST(ts_3, ts_4) can
+ return a value with 3 fractional digits, although its fractional
+ precision is 4. Re-pack with a proper precision now.
+ */
+ Timestamp(native).to_native(&native, item->datetime_precision(thd));
+ }
+ DBUG_ASSERT(native.length() == binlen);
+ memcpy((char *) to, native.ptr(), binlen);
+ return binlen;
+ }
+}
+
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 13b2659789d..fce35bff2f5 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -6255,6 +6255,11 @@ struct SORT_FIELD_ATTR
{
uint length; /* Length of sort field */
uint suffix_length; /* Length suffix (0-4) */
+ /* Max. length of the original value, in bytes */
+ uint original_length;
+
+ uint pack_sort_string(uchar *to, const LEX_CSTRING &str,
+ CHARSET_INFO *cs) const;
};
diff --git a/sql/sql_type.h b/sql/sql_type.h
index ce87c8e9d93..b047871a706 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -29,6 +29,7 @@
#include "sql_type_string.h"
#include "sql_type_real.h"
#include "compat56.h"
+#include "filesort.h"
C_MODE_START
#include <ma_dyncol.h>
C_MODE_END
@@ -86,6 +87,7 @@ class handler;
struct Schema_specification_st;
struct TABLE;
struct SORT_FIELD_ATTR;
+struct SORT_FIELD;
class Vers_history_point;
class Virtual_column_info;
class Conv_source;
@@ -3332,6 +3334,14 @@ protected:
bool maybe_null, bool null_value,
bool unsigned_flag,
longlong value) const;
+ void store_sort_key_longlong(uchar *to, bool unsigned_flag,
+ longlong value) const;
+
+ uint make_packed_sort_key_longlong(uchar *to, bool maybe_null,
+ bool null_value, bool unsigned_flag,
+ longlong value,
+ const SORT_FIELD_ATTR *sort_field) const;
+
bool Item_func_or_sum_illegal_param(const char *name) const;
bool Item_func_or_sum_illegal_param(const Item_func_or_sum *) const;
bool check_null(const Item *item, st_value *value) const;
@@ -3758,6 +3768,15 @@ public:
virtual void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const= 0;
+ virtual bool is_packable() const { return false; }
+
+ /*
+ create a compact sort key which can be compared with a comparison
+ function. They are called packed sort keys
+ */
+ virtual uint make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const=0;
virtual uint32 max_display_length(const Item *item) const= 0;
virtual uint32 Item_decimal_notation_int_digits(const Item *item) const { return 0; }
@@ -4155,6 +4174,13 @@ public:
{
DBUG_ASSERT(0);
}
+ uint make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override
+ {
+ DBUG_ASSERT(0);
+ return 0;
+ }
void sortlength(THD *thd, const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const override
{
@@ -4483,6 +4509,9 @@ public:
const override;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const override;
+ uint make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const override;
@@ -4590,6 +4619,9 @@ public:
const override;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const override;
+ uint make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
void
Column_definition_attributes_frm_pack(const Column_definition_attributes *at,
uchar *buff) const override;
@@ -4840,6 +4872,9 @@ public:
TABLE_SHARE *share) const override;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const override;
+ uint make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
void
Column_definition_attributes_frm_pack(const Column_definition_attributes *at,
uchar *buff) const override;
@@ -4947,6 +4982,9 @@ public:
uchar *buff) const override;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const override;
+ uint make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const override;
@@ -5036,9 +5074,13 @@ public:
CHARSET_INFO *cs) const override;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const override;
+ uint make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const override;
+ bool is_packable()const override { return true; }
bool union_element_finalize(const Item * item) const override;
uint calc_key_length(const Column_definition &def) const override;
bool Column_definition_prepare_stage1(THD *thd,
@@ -6232,6 +6274,9 @@ public:
const override;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const override;
+ uint make_packed_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const override;