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:
@ -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 *,
|
||||
|
Reference in New Issue
Block a user