Many files:

  Fix Bug #1942: do not retrieve all columns in a table if we only need the 'ref' of the row (usually, the PRIMARY KEY) to calculate an ORDER BY
parent 99d37415
......@@ -131,10 +131,14 @@ enum ha_extra_function {
HA_EXTRA_IGNORE_DUP_KEY, /* Dup keys don't rollback everything*/
HA_EXTRA_NO_IGNORE_DUP_KEY,
/*
Instructs InnoDB to retrieve all columns, not just those where
field->query_id is the same as the current query id
Instructs InnoDB to retrieve all columns (except in key read), not just
those where field->query_id is the same as the current query id
*/
HA_EXTRA_RETRIEVE_ALL_COLS,
/*
Instructs InnoDB to retrieve at least all the primary key columns
*/
HA_EXTRA_RETRIEVE_PRIMARY_KEY,
HA_EXTRA_PREPARE_FOR_DELETE,
HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */
HA_EXTRA_PRELOAD_BUFFER_SIZE /* Set buffer size for preloading */
......
......@@ -631,7 +631,7 @@ dict_table_get_on_id(
}
/************************************************************************
Looks for column n postion in the clustered index. */
Looks for column n position in the clustered index. */
ulint
dict_table_get_nth_col_pos(
......@@ -645,6 +645,44 @@ dict_table_get_nth_col_pos(
n));
}
/************************************************************************
Checks if a column is in the ordering columns of the clustered index of a
table. Column prefixes are treated like whole columns. */
ibool
dict_table_col_in_clustered_key(
/*============================*/
/* out: TRUE if the column, or its prefix, is
in the clustered key */
dict_table_t* table, /* in: table */
ulint n) /* in: column number */
{
dict_index_t* index;
dict_field_t* field;
dict_col_t* col;
ulint pos;
ulint n_fields;
ut_ad(table);
col = dict_table_get_nth_col(table, n);
index = dict_table_get_first_index(table);
n_fields = dict_index_get_n_unique(index);
for (pos = 0; pos < n_fields; pos++) {
field = dict_index_get_nth_field(index, pos);
if (col == field->col) {
return(TRUE);
}
}
return(FALSE);
}
/**************************************************************************
Inits the data dictionary module. */
......
......@@ -493,6 +493,17 @@ dict_table_get_sys_col_no(
/* out: column number */
dict_table_t* table, /* in: table */
ulint sys); /* in: DATA_ROW_ID, ... */
/************************************************************************
Checks if a column is in the ordering columns of the clustered index of a
table. Column prefixes are treated like whole columns. */
ibool
dict_table_col_in_clustered_key(
/*============================*/
/* out: TRUE if the column, or its prefix, is
in the clustered key */
dict_table_t* table, /* in: table */
ulint n); /* in: column number */
/***********************************************************************
Copies types of columns contained in table to tuple. */
......
......@@ -510,13 +510,15 @@ struct row_prebuilt_struct {
byte* ins_upd_rec_buff;/* buffer for storing data converted
to the Innobase format from the MySQL
format */
ibool hint_no_need_to_fetch_extra_cols;
/* normally this is TRUE, but
MySQL will set this to FALSE
if we might be required to fetch also
other columns than mentioned in the
query: the clustered index column(s),
or an auto-increment column*/
ulint hint_need_to_fetch_extra_cols;
/* normally this is set to 0; if this
is set to ROW_RETRIEVE_PRIMARY_KEY,
then we should at least retrieve all
columns in the primary key; if this
is set to ROW_RETRIEVE_ALL_COLS, then
we must retrieve all columns in the
key (if read_just_key == 1), or all
columns in the table */
upd_node_t* upd_node; /* Innobase SQL update node used
to perform updates and deletes */
que_fork_t* ins_graph; /* Innobase SQL query graph used
......@@ -572,6 +574,11 @@ struct row_prebuilt_struct {
#define ROW_MYSQL_DUMMY_TEMPLATE 3 /* dummy template used in
row_scan_and_check_index */
/* Values for hint_need_to_fetch_extra_cols */
#define ROW_RETRIEVE_PRIMARY_KEY 1
#define ROW_RETRIEVE_ALL_COLS 2
#ifndef UNIV_NONINL
#include "row0mysql.ic"
#endif
......
......@@ -702,7 +702,7 @@ ha_innobase::init_table_handle_for_HANDLER(void)
/* Always fetch all columns in the index record */
prebuilt->hint_no_need_to_fetch_extra_cols = FALSE;
prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
/* We want always to fetch all columns in the whole row? Or do
we???? */
......@@ -1951,6 +1951,7 @@ build_template(
ulint n_fields;
ulint n_requested_fields = 0;
ibool fetch_all_in_key = FALSE;
ibool fetch_primary_key_cols = FALSE;
ulint i;
if (prebuilt->select_lock_type == LOCK_X) {
......@@ -1961,8 +1962,9 @@ build_template(
templ_type = ROW_MYSQL_WHOLE_ROW;
}
if (templ_type == ROW_MYSQL_REC_FIELDS
&& !prebuilt->hint_no_need_to_fetch_extra_cols) {
if (templ_type == ROW_MYSQL_REC_FIELDS) {
if (prebuilt->hint_need_to_fetch_extra_cols
== ROW_RETRIEVE_ALL_COLS) {
/* We know we must at least fetch all columns in the key, or
all columns in the table */
......@@ -1977,15 +1979,14 @@ build_template(
fetch_all_in_key = TRUE;
} else {
/* We are building a temporary table: fetch all
columns; the reason is that MySQL may use the
clustered index key to store rows, but the mechanism
we use below to detect required columns does not
reveal that. Actually, it might be enough to
fetch only all in the key also in this case! */
templ_type = ROW_MYSQL_WHOLE_ROW;
}
} else if (prebuilt->hint_need_to_fetch_extra_cols
== ROW_RETRIEVE_PRIMARY_KEY) {
/* We must at least fetch all primary key cols */
fetch_primary_key_cols = TRUE;
}
}
clust_index = dict_table_get_first_index_noninline(prebuilt->table);
......@@ -2004,7 +2005,7 @@ build_template(
the clustered index */
}
n_fields = (ulint)table->fields;
n_fields = (ulint)table->fields; /* number of columns */
if (!prebuilt->mysql_template) {
prebuilt->mysql_template = (mysql_row_templ_t*)
......@@ -2017,6 +2018,8 @@ build_template(
prebuilt->templ_contains_blob = FALSE;
/* Note that in InnoDB, i is the column number. MySQL calls columns
'fields'. */
for (i = 0; i < n_fields; i++) {
templ = prebuilt->mysql_template + n_requested_fields;
field = table->field[i];
......@@ -2029,6 +2032,8 @@ build_template(
if (templ_type == ROW_MYSQL_REC_FIELDS
&& !(fetch_all_in_key
&& dict_index_contains_col_or_prefix(index, i))
&& !(fetch_primary_key_cols
&& dict_table_col_in_clustered_key(index->table, i))
&& thd->query_id != field->query_id) {
/* This field is not needed in the query, skip it */
......@@ -4514,7 +4519,14 @@ ha_innobase::extra(
prebuilt->read_just_key = 0;
break;
case HA_EXTRA_RETRIEVE_ALL_COLS:
prebuilt->hint_no_need_to_fetch_extra_cols = FALSE;
prebuilt->hint_need_to_fetch_extra_cols
= ROW_RETRIEVE_ALL_COLS;
break;
case HA_EXTRA_RETRIEVE_PRIMARY_KEY:
if (prebuilt->hint_need_to_fetch_extra_cols == 0) {
prebuilt->hint_need_to_fetch_extra_cols
= ROW_RETRIEVE_PRIMARY_KEY;
}
break;
case HA_EXTRA_KEYREAD:
prebuilt->read_just_key = 1;
......@@ -4575,7 +4587,7 @@ ha_innobase::start_stmt(
auto_inc_counter_for_this_stat = 0;
prebuilt->sql_stat_start = TRUE;
prebuilt->hint_no_need_to_fetch_extra_cols = TRUE;
prebuilt->hint_need_to_fetch_extra_cols = 0;
prebuilt->read_just_key = 0;
if (!prebuilt->mysql_has_locked) {
......@@ -4652,7 +4664,7 @@ ha_innobase::external_lock(
trx = prebuilt->trx;
prebuilt->sql_stat_start = TRUE;
prebuilt->hint_no_need_to_fetch_extra_cols = TRUE;
prebuilt->hint_need_to_fetch_extra_cols = 0;
prebuilt->read_just_key = 0;
......@@ -4996,7 +5008,7 @@ ha_innobase::innobase_read_and_init_auto_inc(
/* Play safe and also give in another way the hint to fetch
all columns in the key: */
prebuilt->hint_no_need_to_fetch_extra_cols = FALSE;
prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
prebuilt->trx->mysql_n_tables_locked += 1;
......
......@@ -845,7 +845,7 @@ JOIN::optimize()
for (uint i_h = const_tables; i_h < tables; i_h++)
{
TABLE* table_h = join_tab[i_h].table;
table_h->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
table_h->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
}
}
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment