1
0
mirror of https://github.com/MariaDB/server.git synced 2025-12-24 11:21:21 +03:00

Backport into MariaDB-5.2 the following:

WL#2474 "Multi Range Read: Change the default MRR implementation to implement new MRR interface"
WL#2475 "Batched range read functions for MyISAM/InnoDb"
        "Index condition pushdown for MyISAM/InnoDB"
Igor's fix from sp1r-igor@olga.mysql.com-20080330055902-07614:
  There could be observed the following problems:
  1. EXPLAIN did not mention pushdown conditions from on expressions in the 
  'extra' column.  As a result if a query had no where conditions pushed 
  down to a table, but had on conditions pushed to this table the 'extra' 
  column in the EXPLAIN for the table missed 'using where'.
  2. Conditions for ref access were not eliminated from on expressions 
  though such conditions were eliminated from the where condition.
This commit is contained in:
Sergey Petrunya
2009-12-15 10:16:46 +03:00
parent e4e1ae0d13
commit 96e092dc73
136 changed files with 18754 additions and 1169 deletions

View File

@@ -114,13 +114,16 @@ class QUICK_RANGE :public Sql_alloc {
4. Delete the select:
delete quick;
NOTE
quick select doesn't use Sql_alloc/MEM_ROOT allocation because "range
checked for each record" functionality may create/destroy
O(#records_in_some_table) quick selects during query execution.
*/
class QUICK_SELECT_I
{
public:
bool sorted;
ha_rows records; /* estimate of # of records to be retrieved */
double read_time; /* time to perform this retrieval */
TABLE *head;
@@ -193,6 +196,12 @@ public:
virtual bool reverse_sorted() = 0;
virtual bool unique_key_range() { return false; }
/*
Request that this quick select produces sorted output. Not all quick
selects can do it, the caller is responsible for calling this function
only for those quick selects that can.
*/
virtual void need_sorted_output() = 0;
enum {
QS_TYPE_RANGE = 0,
QS_TYPE_INDEX_MERGE = 1,
@@ -272,67 +281,68 @@ struct st_qsel_param;
class PARAM;
class SEL_ARG;
/*
MRR range sequence, array<QUICK_RANGE> implementation: sequence traversal
context.
*/
typedef struct st_quick_range_seq_ctx
{
QUICK_RANGE **first;
QUICK_RANGE **cur;
QUICK_RANGE **last;
} QUICK_RANGE_SEQ_CTX;
range_seq_t quick_range_seq_init(void *init_param, uint n_ranges, uint flags);
uint quick_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range);
/*
Quick select that does a range scan on a single key. The records are
returned in key order.
*/
class QUICK_RANGE_SELECT : public QUICK_SELECT_I
{
protected:
bool next,dont_free,in_ror_merged_scan;
public:
int error;
protected:
handler *file;
/*
If true, this quick select has its "own" handler object which should be
closed no later then this quick select is deleted.
*/
bool free_file;
bool in_range;
uint multi_range_count; /* copy from thd->variables.multi_range_count */
uint multi_range_length; /* the allocated length for the array */
uint multi_range_bufsiz; /* copy from thd->variables.read_rnd_buff_size */
KEY_MULTI_RANGE *multi_range; /* the multi-range array (allocated and
freed by QUICK_RANGE_SELECT) */
HANDLER_BUFFER *multi_range_buff; /* the handler buffer (allocated and
freed by QUICK_RANGE_SELECT) */
/* Members to deal with case when this quick select is a ROR-merged scan */
bool in_ror_merged_scan;
MY_BITMAP column_bitmap, *save_read_set, *save_write_set;
bool free_file; /* TRUE <=> this->file is "owned" by this quick select */
friend class TRP_ROR_INTERSECT;
friend
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
struct st_table_ref *ref,
ha_rows records);
friend bool get_quick_keys(PARAM *param,
QUICK_RANGE_SELECT *quick,KEY_PART *key,
SEL_ARG *key_tree,
uchar *min_key, uint min_key_flag,
uchar *max_key, uint max_key_flag);
friend QUICK_RANGE_SELECT *get_quick_select(PARAM*,uint idx,
SEL_ARG *key_tree,
MEM_ROOT *alloc);
friend class QUICK_SELECT_DESC;
friend class QUICK_INDEX_MERGE_SELECT;
friend class QUICK_ROR_INTERSECT_SELECT;
friend class QUICK_GROUP_MIN_MAX_SELECT;
/* Range pointers to be used when not using MRR interface */
/* Members needed to use the MRR interface */
QUICK_RANGE_SEQ_CTX qr_traversal_ctx;
public:
uint mrr_flags; /* Flags to be used with MRR interface */
protected:
uint mrr_buf_size; /* copy from thd->variables.read_rnd_buff_size */
HANDLER_BUFFER *mrr_buf_desc; /* the handler buffer */
/* Info about index we're scanning */
DYNAMIC_ARRAY ranges; /* ordered array of range ptrs */
QUICK_RANGE **cur_range; /* current element in ranges */
QUICK_RANGE *last_range;
KEY_PART *key_parts;
KEY_PART_INFO *key_part_info;
bool dont_free; /* Used by QUICK_SELECT_DESC */
int cmp_next(QUICK_RANGE *range);
int cmp_prev(QUICK_RANGE *range);
bool row_in_ranges();
public:
MEM_ROOT alloc;
QUICK_RANGE_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc=0,
MEM_ROOT *parent_alloc=NULL);
QUICK_RANGE_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc,
MEM_ROOT *parent_alloc, bool *create_err);
~QUICK_RANGE_SELECT();
void need_sorted_output();
int init();
int reset(void);
int get_next();
@@ -352,6 +362,27 @@ public:
#endif
private:
/* Default copy ctor used by QUICK_SELECT_DESC */
friend class TRP_ROR_INTERSECT;
friend
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
struct st_table_ref *ref,
ha_rows records);
friend bool get_quick_keys(PARAM *param, QUICK_RANGE_SELECT *quick,
KEY_PART *key, SEL_ARG *key_tree,
uchar *min_key, uint min_key_flag,
uchar *max_key, uint max_key_flag);
friend QUICK_RANGE_SELECT *get_quick_select(PARAM*,uint idx,
SEL_ARG *key_tree,
uint mrr_flags,
uint mrr_buf_size,
MEM_ROOT *alloc);
friend class QUICK_SELECT_DESC;
friend class QUICK_INDEX_MERGE_SELECT;
friend class QUICK_ROR_INTERSECT_SELECT;
friend class QUICK_GROUP_MIN_MAX_SELECT;
friend uint quick_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range);
friend range_seq_t quick_range_seq_init(void *init_param,
uint n_ranges, uint flags);
};
@@ -359,8 +390,10 @@ class QUICK_RANGE_SELECT_GEOM: public QUICK_RANGE_SELECT
{
public:
QUICK_RANGE_SELECT_GEOM(THD *thd, TABLE *table, uint index_arg,
bool no_alloc, MEM_ROOT *parent_alloc)
:QUICK_RANGE_SELECT(thd, table, index_arg, no_alloc, parent_alloc)
bool no_alloc, MEM_ROOT *parent_alloc,
bool *create_err)
:QUICK_RANGE_SELECT(thd, table, index_arg, no_alloc, parent_alloc,
create_err)
{};
virtual int get_next();
};
@@ -432,6 +465,7 @@ public:
~QUICK_INDEX_MERGE_SELECT();
int init();
void need_sorted_output() { DBUG_ASSERT(0); /* Can't do it */ }
int reset(void);
int get_next();
bool reverse_sorted() { return false; }
@@ -491,6 +525,7 @@ public:
~QUICK_ROR_INTERSECT_SELECT();
int init();
void need_sorted_output() { DBUG_ASSERT(0); /* Can't do it */ }
int reset(void);
int get_next();
bool reverse_sorted() { return false; }
@@ -545,6 +580,7 @@ public:
~QUICK_ROR_UNION_SELECT();
int init();
void need_sorted_output() { DBUG_ASSERT(0); /* Can't do it */ }
int reset(void);
int get_next();
bool reverse_sorted() { return false; }
@@ -664,6 +700,7 @@ public:
void adjust_prefix_ranges();
bool alloc_buffers();
int init();
void need_sorted_output() { /* always do it */ }
int reset();
int get_next();
bool reverse_sorted() { return false; }
@@ -679,7 +716,8 @@ public:
class QUICK_SELECT_DESC: public QUICK_RANGE_SELECT
{
public:
QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q, uint used_key_parts);
QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q, uint used_key_parts,
bool *create_err);
int get_next();
bool reverse_sorted() { return 1; }
int get_type() { return QS_TYPE_RANGE_DESC; }
@@ -712,25 +750,29 @@ class SQL_SELECT :public Sql_alloc {
{
key_map tmp;
tmp.set_all();
return test_quick_select(thd, tmp, 0, limit, force_quick_range) < 0;
return test_quick_select(thd, tmp, 0, limit, force_quick_range, FALSE) < 0;
}
inline bool skip_record() { return cond ? cond->val_int() == 0 : 0; }
int test_quick_select(THD *thd, key_map keys, table_map prev_tables,
ha_rows limit, bool force_quick_range);
ha_rows limit, bool force_quick_range,
bool ordered_output);
};
class FT_SELECT: public QUICK_RANGE_SELECT {
class FT_SELECT: public QUICK_RANGE_SELECT
{
public:
FT_SELECT(THD *thd, TABLE *table, uint key) :
QUICK_RANGE_SELECT (thd, table, key, 1) { VOID(init()); }
FT_SELECT(THD *thd, TABLE *table, uint key, bool *create_err) :
QUICK_RANGE_SELECT (thd, table, key, 1, NULL, create_err)
{ (void) init(); }
~FT_SELECT() { file->ft_end(); }
int init() { return error=file->ft_init(); }
int init() { return file->ft_init(); }
int reset() { return 0; }
int get_next() { return error= file->ha_ft_read(record); }
int get_next() { return file->ha_ft_read(record); }
int get_type() { return QS_TYPE_FULLTEXT; }
};
FT_SELECT *get_ft_select(THD *thd, TABLE *table, uint key);
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
struct st_table_ref *ref,
ha_rows records);