1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

MDEV-32148 Inefficient WHERE timestamp_column=datetime_const_expr

Changing the way how a the following conditions are evaluated:

    WHERE timestamp_column=datetime_const_expr

(for all comparison operators: =, <=>, <, >, <=, >=, <> and for NULLIF)

Before the change it was always performed as DATETIME.
That was not efficient, as involved per-row TIMESTAMP->DATETIME conversion
for timestamp_column. For example, in case of the SYSTEM time zone
it involved a localtime_r() call, which is known to be slow.

After the change it's performed as TIMESTAMP in many cases.
This allows to avoid per-row conversion, as it works the other way around:
datetime_const_expr is converted to TIMESTAMP once before the execution stage.

Note, datetime_const_expr must be inside monotone continuous periods of
the current time zone, i.e. not near these anomalies:
- DST changes (spring forward, fall back)
- leap seconds
This commit is contained in:
Alexander Barkov
2023-09-12 11:27:54 +04:00
parent af4f9daeb8
commit 351a8eecf0
23 changed files with 1543 additions and 24 deletions

View File

@ -2837,6 +2837,11 @@ public:
class Timestamp_or_zero_datetime: protected Timestamp
{
bool m_is_zero_datetime;
public:
static Timestamp_or_zero_datetime zero()
{
return Timestamp_or_zero_datetime(Timestamp(0, 0), true);
}
public:
Timestamp_or_zero_datetime()
:Timestamp(0,0), m_is_zero_datetime(true)
@ -2845,7 +2850,7 @@ public:
:Timestamp(native.length() ? Timestamp(native) : Timestamp(0,0)),
m_is_zero_datetime(native.length() == 0)
{ }
Timestamp_or_zero_datetime(const Timestamp &tm, bool is_zero_datetime)
Timestamp_or_zero_datetime(const Timestamp &tm, bool is_zero_datetime= false)
:Timestamp(tm), m_is_zero_datetime(is_zero_datetime)
{ }
Timestamp_or_zero_datetime(THD *thd, const MYSQL_TIME *ltime, uint *err_code);
@ -2869,6 +2874,11 @@ public:
return 1;
return Timestamp::cmp(other);
}
const Timestamp &to_timestamp() const
{
DBUG_ASSERT(!is_zero_datetime());
return *this;
}
bool to_TIME(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) const;
/*
Convert to native format:
@ -4206,6 +4216,33 @@ public:
virtual Item *make_const_item_for_comparison(THD *thd,
Item *src,
const Item *cmp) const= 0;
/**
When aggregating function arguments for comparison
(e.g. for =, <, >, <=, >=, NULLIF), in some cases we rewrite
arguments. For example, if the predicate
timestamp_expr0 = datetime_const_expr1
decides to compare arguments as DATETIME,
we can try to rewrite datetime_const_expr1 to a TIMESTAMP constant
and perform the comparison as TIMESTAMP, which is faster because
does not have to perform TIMESTAMP->DATETIME data type conversion per row.
"this" is the type handler that is used to compare
"subject" and "counterpart" (DATETIME in the above example).
@param thd the current thread
@param subject the comparison side that we want try to rewrite
@param counterpart the other comparison side
@retval subject, if the subject does not need to be rewritten
@retval NULL in case of error (e.g. EOM)
@retval Otherwise, a pointer to a new Item which can
be used as a replacement for the subject.
*/
virtual Item *convert_item_for_comparison(THD *thd,
Item *subject,
const Item *counterpart) const
{
return subject;
}
virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0;
virtual Item *make_constructor_item(THD *thd, List<Item> *args) const
{
@ -6524,6 +6561,9 @@ public:
}
String *print_item_value(THD *thd, Item *item, String *str) const override;
Item_cache *Item_get_cache(THD *thd, const Item *item) const override;
Item *convert_item_for_comparison(THD *thd,
Item *subject,
const Item *counterpart) const override;
String *Item_func_min_max_val_str(Item_func_min_max *, String *) const override;
double Item_func_min_max_val_real(Item_func_min_max *) const override;
longlong Item_func_min_max_val_int(Item_func_min_max *) const override;
@ -6695,6 +6735,8 @@ public:
my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *,
my_decimal *) const override;
bool set_comparator_func(THD *thd, Arg_comparator *cmp) const override;
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const override;
bool Item_hybrid_func_fix_attributes(THD *thd,
const LEX_CSTRING &name,
Type_handler_hybrid_field_type *,