summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Mathew <jacob.mathew@mariadb.com>2017-05-01 16:04:47 -0700
committerJacob Mathew <jacob.mathew@mariadb.com>2017-05-01 16:04:47 -0700
commit7afcee4cf66c73ae3f9c5f04763b4b7a1d37e419 (patch)
tree61bf514a7845c604aed39a84f609eb3959f5d6e2
parent5ccaabe9620bcf9e960ae019d7e27e5998a772bd (diff)
downloadmariadb-git-7afcee4cf66c73ae3f9c5f04763b4b7a1d37e419.tar.gz
MDEV-8954 unnecessary fetch of entire table
Merged fix into 10.2.
-rw-r--r--storage/spider/ha_spider.cc80
-rw-r--r--storage/spider/ha_spider.h2
-rw-r--r--storage/spider/spd_db_handlersocket.cc9
-rw-r--r--storage/spider/spd_db_handlersocket.h3
-rw-r--r--storage/spider/spd_db_include.h3
-rw-r--r--storage/spider/spd_db_mysql.cc59
-rw-r--r--storage/spider/spd_db_mysql.h3
-rw-r--r--storage/spider/spd_db_oracle.cc59
-rw-r--r--storage/spider/spd_db_oracle.h3
9 files changed, 221 insertions, 0 deletions
diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc
index 6ded5992c79..d6a5a20df8f 100644
--- a/storage/spider/ha_spider.cc
+++ b/storage/spider/ha_spider.cc
@@ -2109,6 +2109,7 @@ int ha_spider::index_read_map_internal(
result_list.desc_flg = FALSE;
result_list.sorted = TRUE;
result_list.key_info = &table->key_info[active_index];
+ check_distinct_key_query();
result_list.limit_num =
result_list.internal_limit >= result_list.split_read ?
result_list.split_read : result_list.internal_limit;
@@ -2624,6 +2625,7 @@ int ha_spider::index_read_last_map_internal(
result_list.desc_flg = TRUE;
result_list.sorted = TRUE;
result_list.key_info = &table->key_info[active_index];
+ check_distinct_key_query();
result_list.limit_num =
result_list.internal_limit >= result_list.split_read ?
result_list.split_read : result_list.internal_limit;
@@ -3089,6 +3091,7 @@ int ha_spider::index_first_internal(
result_list.sorted = TRUE;
result_list.key_info = &table->key_info[active_index];
result_list.key_order = 0;
+ check_distinct_key_query();
result_list.limit_num =
result_list.internal_limit >= result_list.split_read ?
result_list.split_read : result_list.internal_limit;
@@ -3472,6 +3475,7 @@ int ha_spider::index_last_internal(
result_list.sorted = TRUE;
result_list.key_info = &table->key_info[active_index];
result_list.key_order = 0;
+ check_distinct_key_query();
result_list.limit_num =
result_list.internal_limit >= result_list.split_read ?
result_list.split_read : result_list.internal_limit;
@@ -3914,6 +3918,7 @@ int ha_spider::read_range_first_internal(
result_list.desc_flg = FALSE;
result_list.sorted = sorted;
result_list.key_info = &table->key_info[active_index];
+ check_distinct_key_query();
result_list.limit_num =
result_list.internal_limit >= result_list.split_read ?
result_list.split_read : result_list.internal_limit;
@@ -12077,6 +12082,81 @@ void ha_spider::check_direct_order_limit()
DBUG_VOID_RETURN;
}
+/********************************************************************
+ * Check whether the current query is a SELECT DISTINCT using an
+ * index in a non-partitioned Spider configuration, with a
+ * projection list that consists solely of the first key prefix
+ * column.
+ *
+ * For a SELECT DISTINCT query using an index in a non-partitioned
+ * Spider configuration, with a projection list that consists
+ * solely of the first key prefix, set the internal row retrieval
+ * limit to avoid visiting each row multiple times.
+ ********************************************************************/
+void ha_spider::check_distinct_key_query()
+{
+ DBUG_ENTER( "ha_spider::check_distinct_key_query" );
+
+ if ( result_list.direct_distinct && !partition_handler_share->handlers &&
+ result_list.keyread && result_list.check_direct_order_limit )
+ {
+ // SELECT DISTINCT query using an index in a non-partitioned configuration
+ KEY_PART_INFO* key_part = result_list.key_info->key_part;
+ Field* key_field = key_part->field;
+
+ if ( is_sole_projection_field( key_field->field_index ) )
+ {
+ // Projection list consists solely of the first key prefix column
+
+ // Set the internal row retrieval limit to avoid visiting each row
+ // multiple times. This fixes a Spider performance bug that
+ // caused each row to be visited multiple times.
+ result_list.internal_limit = 1;
+ }
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+/********************************************************************
+ * Determine whether the current query's projection list
+ * consists solely of the specified column.
+ *
+ * Params IN - field_index:
+ * Field index of the column of interest within
+ * its table.
+ *
+ * Returns TRUE - if the query's projection list consists
+ * solely of the specified column.
+ * FALSE - otherwise.
+ ********************************************************************/
+bool ha_spider::is_sole_projection_field( uint16 field_index )
+{
+ // NOTE: It is assumed that spider_db_append_select_columns() has already been called
+ // to build the bitmap of projection fields
+ bool is_ha_sole_projection_field;
+ uint loop_index, dbton_id;
+ spider_db_handler* dbton_hdl;
+ DBUG_ENTER( "ha_spider::is_sole_projection_field" );
+
+ for ( loop_index = 0; loop_index < share->use_sql_dbton_count; loop_index++ )
+ {
+ dbton_id = share->use_sql_dbton_ids[ loop_index ];
+ dbton_hdl = dbton_handler[ dbton_id ];
+
+ if ( dbton_hdl->first_link_idx >= 0 )
+ {
+ is_ha_sole_projection_field = dbton_hdl->is_sole_projection_field( field_index );
+ if ( !is_ha_sole_projection_field )
+ {
+ DBUG_RETURN( FALSE );
+ }
+ }
+ }
+
+ DBUG_RETURN( TRUE );
+}
+
int ha_spider::check_ha_range_eof()
{
DBUG_ENTER("ha_spider::check_ha_range_eof");
diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h
index 50d890dc854..acc75ed1c05 100644
--- a/storage/spider/ha_spider.h
+++ b/storage/spider/ha_spider.h
@@ -751,6 +751,8 @@ public:
);
uint check_partitioned();
void check_direct_order_limit();
+ void check_distinct_key_query();
+ bool is_sole_projection_field( uint16 field_index );
int check_ha_range_eof();
int drop_tmp_tables();
bool handler_opened(
diff --git a/storage/spider/spd_db_handlersocket.cc b/storage/spider/spd_db_handlersocket.cc
index 47f22b04116..32acb8df6fb 100644
--- a/storage/spider/spd_db_handlersocket.cc
+++ b/storage/spider/spd_db_handlersocket.cc
@@ -4994,6 +4994,15 @@ int spider_handlersocket_handler::append_explain_select_part(
DBUG_RETURN(0);
}
+int spider_handlersocket_handler::is_sole_projection_field(
+ uint16 field_index
+) {
+ DBUG_ENTER("spider_handlersocket_handler::is_sole_projection_field");
+ DBUG_PRINT("info", ("spider this=%p", this));
+ DBUG_ASSERT(0);
+ DBUG_RETURN(0);
+}
+
bool spider_handlersocket_handler::is_bulk_insert_exec_period(
bool bulk_end
) {
diff --git a/storage/spider/spd_db_handlersocket.h b/storage/spider/spd_db_handlersocket.h
index d3fdf5564b7..a3955aea044 100644
--- a/storage/spider/spd_db_handlersocket.h
+++ b/storage/spider/spd_db_handlersocket.h
@@ -776,6 +776,9 @@ public:
ulong sql_type,
int link_idx
);
+ bool is_sole_projection_field(
+ uint16 field_index
+ );
bool is_bulk_insert_exec_period(
bool bulk_end
);
diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h
index 936951d3860..56bc2ccad42 100644
--- a/storage/spider/spd_db_include.h
+++ b/storage/spider/spd_db_include.h
@@ -1279,6 +1279,9 @@ public:
ulong sql_type,
int link_idx
) = 0;
+ virtual bool is_sole_projection_field(
+ uint16 field_index
+ ) = 0;
virtual bool is_bulk_insert_exec_period(
bool bulk_end
) = 0;
diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc
index 1c1c440c2ed..9974b6b0628 100644
--- a/storage/spider/spd_db_mysql.cc
+++ b/storage/spider/spd_db_mysql.cc
@@ -9516,6 +9516,65 @@ int spider_mysql_handler::append_explain_select(
DBUG_RETURN(0);
}
+/********************************************************************
+ * Determine whether the current query's projection list
+ * consists solely of the specified column.
+ *
+ * Params IN - field_index:
+ * Field index of the column of interest within
+ * its table.
+ *
+ * Returns TRUE - if the query's projection list consists
+ * solely of the specified column.
+ * FALSE - otherwise.
+ ********************************************************************/
+bool spider_mysql_handler::is_sole_projection_field( uint16 field_index )
+{
+ // Determine whether the projection list consists solely of the field of interest
+ bool is_field_in_projection_list = FALSE;
+ TABLE* table = spider->get_table();
+ uint16 projection_field_count = 0;
+ uint16 projection_field_index;
+ Field** field;
+ DBUG_ENTER( "spider_mysql_handler::is_sole_projection_field" );
+
+ for ( field = table->field; *field ; field++ )
+ {
+ projection_field_index = ( *field )->field_index;
+
+ if ( !( minimum_select_bit_is_set( projection_field_index ) ) )
+ {
+ // Current field is not in the projection list
+ continue;
+ }
+
+ projection_field_count++;
+
+ if ( !is_field_in_projection_list )
+ {
+ if ( field_index == projection_field_index )
+ {
+ // Field of interest is in the projection list
+ is_field_in_projection_list = TRUE;
+ }
+ }
+
+ if ( is_field_in_projection_list && ( projection_field_count != 1 ) )
+ {
+ // Field of interest is not the sole column in the projection list
+ DBUG_RETURN( FALSE );
+ }
+ }
+
+ if ( is_field_in_projection_list && ( projection_field_count == 1 ) )
+ {
+ // Field of interest is the only column in the projection list
+ DBUG_RETURN( TRUE );
+ }
+
+ DBUG_RETURN( FALSE );
+}
+
bool spider_mysql_handler::is_bulk_insert_exec_period(
bool bulk_end
) {
diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h
index 9a4f08ade98..482289d1d68 100644
--- a/storage/spider/spd_db_mysql.h
+++ b/storage/spider/spd_db_mysql.h
@@ -1128,6 +1128,9 @@ public:
ulong sql_type,
int link_idx
);
+ bool is_sole_projection_field(
+ uint16 field_index
+ );
bool is_bulk_insert_exec_period(
bool bulk_end
);
diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc
index c3dfe8b8cf2..94f354e0a0f 100644
--- a/storage/spider/spd_db_oracle.cc
+++ b/storage/spider/spd_db_oracle.cc
@@ -9571,6 +9571,65 @@ int spider_oracle_handler::append_explain_select(
DBUG_RETURN(0);
}
+/********************************************************************
+ * Determine whether the current query's projection list
+ * consists solely of the specified column.
+ *
+ * Params IN - field_index:
+ * Field index of the column of interest within
+ * its table.
+ *
+ * Returns TRUE - if the query's projection list consists
+ * solely of the specified column.
+ * FALSE - otherwise.
+ ********************************************************************/
+bool spider_oracle_handler::is_sole_projection_field( uint16 field_index )
+{
+ // Determine whether the projection list consists solely of the field of interest
+ bool is_field_in_projection_list = FALSE;
+ TABLE* table = spider->get_table();
+ uint16 projection_field_count = 0;
+ uint16 projection_field_index;
+ Field** field;
+ DBUG_ENTER( "spider_oracle_handler::is_sole_projection_field" );
+
+ for ( field = table->field; *field; field++ )
+ {
+ projection_field_index = ( *field )->field_index;
+
+ if ( !( minimum_select_bit_is_set( projection_field_index ) ) )
+ {
+ // Current field is not in the projection list
+ continue;
+ }
+
+ projection_field_count++;
+
+ if ( !is_field_in_projection_list )
+ {
+ if (field_index == projection_field_index)
+ {
+ // Field of interest is in the projection list
+ is_field_in_projection_list = TRUE;
+ }
+ }
+
+ if ( is_field_in_projection_list && ( projection_field_count != 1 ) )
+ {
+ // Field of interest is not the sole column in the projection list
+ DBUG_RETURN( FALSE );
+ }
+ }
+
+ if ( is_field_in_projection_list && ( projection_field_count == 1 ) )
+ {
+ // Field of interest is the only column in the projection list
+ DBUG_RETURN( TRUE );
+ }
+
+ DBUG_RETURN( FALSE );
+}
+
bool spider_oracle_handler::is_bulk_insert_exec_period(
bool bulk_end
) {
diff --git a/storage/spider/spd_db_oracle.h b/storage/spider/spd_db_oracle.h
index 0e84435d9be..7a070f498da 100644
--- a/storage/spider/spd_db_oracle.h
+++ b/storage/spider/spd_db_oracle.h
@@ -1208,6 +1208,9 @@ public:
ulong sql_type,
int link_idx
);
+ bool is_sole_projection_field(
+ uint16 field_index
+ );
bool is_bulk_insert_exec_period(
bool bulk_end
);