diff options
author | Alexander Barkov <bar@mariadb.com> | 2020-08-22 15:22:20 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2020-08-22 15:22:20 +0400 |
commit | 2e5d86f49e7ee538806fba68dc8c960d6acdd483 (patch) | |
tree | aec0e6903f5decc8c3cdd70111d845ca43e3120e | |
parent | ae33ebe5b32a82629a40e51c8d6c6611842fbd03 (diff) | |
download | mariadb-git-2e5d86f49e7ee538806fba68dc8c960d6acdd483.tar.gz |
MDEV-23537 Comparison with temporal columns is slow in MariaDB
Implementing methods:
- Field::val_time_packed()
- Field::val_datetime_packed()
- Item_field::val_datetime_packed(THD *thd);
- Item_field::val_time_packed(THD *thd);
to give a faster access to temporal packed longlong representation of a Field,
which is used in temporal Arg_comparator's to DATE, TIME, DATETIME data types.
The same idea is used in MySQL-5.6+.
This improves performance.
-rw-r--r-- | sql/field.cc | 56 | ||||
-rw-r--r-- | sql/field.h | 5 | ||||
-rw-r--r-- | sql/item.cc | 18 | ||||
-rw-r--r-- | sql/item.h | 2 | ||||
-rw-r--r-- | sql/sql_type.h | 7 |
5 files changed, 88 insertions, 0 deletions
diff --git a/sql/field.cc b/sql/field.cc index 65dc7f768a3..bac5dd95b5a 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2328,6 +2328,33 @@ bool Field::get_date(MYSQL_TIME *to, date_mode_t mode) return !t->is_valid_temporal(); } + +longlong Field::val_datetime_packed(THD *thd) +{ + MYSQL_TIME ltime, tmp; + if (get_date(<ime, Datetime::Options_cmp(thd))) + return 0; + if (ltime.time_type != MYSQL_TIMESTAMP_TIME) + return pack_time(<ime); + if (time_to_datetime_with_warn(thd, <ime, &tmp, TIME_CONV_NONE)) + return 0; + return pack_time(&tmp); +} + + +longlong Field::val_time_packed(THD *thd) +{ + MYSQL_TIME ltime; + Time::Options_cmp opt(thd); + if (get_date(<ime, opt)) + return 0; + if (ltime.time_type == MYSQL_TIMESTAMP_TIME) + return pack_time(<ime); + // Conversion from DATETIME or DATE to TIME is needed + return Time(thd, <ime, opt).to_packed(); +} + + /** This is called when storing a date in a string. @@ -6272,6 +6299,17 @@ bool Field_timef::get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) return false; } + +longlong Field_timef::val_time_packed(THD *thd) +{ + DBUG_ASSERT(marked_for_read()); + longlong tmp= my_time_packed_from_binary(ptr, dec); + MYSQL_TIME ltime; + TIME_from_longlong_time_packed(<ime, tmp); + return pack_time(<ime); +} + + int Field_timef::store_native(const Native &value) { DBUG_ASSERT(value.length() == my_time_binary_length(dec)); @@ -6673,6 +6711,14 @@ bool Field_newdate::get_TIME(MYSQL_TIME *ltime, const uchar *pos, } +longlong Field_newdate::val_datetime_packed(THD *thd) +{ + MYSQL_TIME ltime; + Field_newdate::get_date(<ime, date_mode_t(0)); + return pack_time(<ime); +} + + int Field_newdate::cmp(const uchar *a_ptr, const uchar *b_ptr) { uint32 a,b; @@ -7008,6 +7054,16 @@ bool Field_datetimef::get_TIME(MYSQL_TIME *ltime, const uchar *pos, return validate_MMDD(tmp, ltime->month, ltime->day, fuzzydate); } +longlong Field_datetimef::val_datetime_packed(THD *thd) +{ + DBUG_ASSERT(marked_for_read()); + longlong tmp= my_datetime_packed_from_binary(ptr, dec); + MYSQL_TIME ltime; + TIME_from_longlong_datetime_packed(<ime, tmp); + return pack_time(<ime); +} + + /**************************************************************************** ** string type ** A string may be varchar or binary diff --git a/sql/field.h b/sql/field.h index 0ee4aca5f69..b3bc2d4dbea 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1401,6 +1401,8 @@ public: void copy_from_tmp(int offset); uint fill_cache_field(struct st_cache_field *copy); virtual bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); + virtual longlong val_datetime_packed(THD *thd); + virtual longlong val_time_packed(THD *thd); virtual TYPELIB *get_typelib() const { return NULL; } virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; } virtual CHARSET_INFO *charset_for_protocol(void) const @@ -3167,6 +3169,7 @@ public: void sql_type(String &str) const; bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) { return Field_newdate::get_TIME(ltime, ptr, fuzzydate); } + longlong val_datetime_packed(THD *thd); uint size_of() const { return sizeof(*this); } Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item); }; @@ -3336,6 +3339,7 @@ public: } int reset(); bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); + longlong val_time_packed(THD *thd); int store_native(const Native &value); bool val_native(Native *to); uint size_of() const { return sizeof(*this); } @@ -3495,6 +3499,7 @@ public: int reset(); bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) { return Field_datetimef::get_TIME(ltime, ptr, fuzzydate); } + longlong val_datetime_packed(THD *thd); uint size_of() const { return sizeof(*this); } }; diff --git a/sql/item.cc b/sql/item.cc index 312effeb6c1..22a8cb169b3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3246,6 +3246,24 @@ bool Item_field::val_native_result(THD *thd, Native *to) } +longlong Item_field::val_datetime_packed(THD *thd) +{ + DBUG_ASSERT(fixed == 1); + if ((null_value= field->is_null())) + return 0; + return field->val_datetime_packed(thd); +} + + +longlong Item_field::val_time_packed(THD *thd) +{ + DBUG_ASSERT(fixed == 1); + if ((null_value= field->is_null())) + return 0; + return field->val_time_packed(thd); +} + + void Item_field::save_result(Field *to) { save_field_in_field(result_field, &null_value, to, TRUE); diff --git a/sql/item.h b/sql/item.h index aced2ec5f0d..95ca06ac211 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3418,6 +3418,8 @@ public: longlong val_int_endpoint(bool left_endp, bool *incl_endp); bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); bool get_date_result(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate); + longlong val_datetime_packed(THD *thd); + longlong val_time_packed(THD *thd); bool is_null() { return field->is_null(); } void update_null_value(); void update_table_bitmaps() diff --git a/sql/sql_type.h b/sql/sql_type.h index 553d204d806..8726208b788 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -1542,6 +1542,13 @@ public: Time(int *warn, bool neg, ulonglong hour, uint minute, const Sec6 &second); Time() { time_type= MYSQL_TIMESTAMP_NONE; } Time(const Native &native); + Time(THD *thd, const MYSQL_TIME *ltime, const Options opt) + { + *(static_cast<MYSQL_TIME*>(this))= *ltime; + DBUG_ASSERT(is_valid_temporal()); + int warn= 0; + valid_MYSQL_TIME_to_valid_value(thd, &warn, opt); + } Time(Item *item) :Time(current_thd, item) { } |