Commit eb210e5f authored by Zardosht Kasheff's avatar Zardosht Kasheff Committed by Yoni Fogel

[t:2425], make insert ignore and replace into optimizations work properly

git-svn-id: file:///svn/mysql/tokudb-engine/tokudb-engine@18212 c7de825b-a66e-492c-adef-691d508d4ae1
parent f29eefaf
...@@ -271,6 +271,34 @@ const char **ha_tokudb::bas_ext() const { ...@@ -271,6 +271,34 @@ const char **ha_tokudb::bas_ext() const {
DBUG_RETURN(ha_tokudb_exts); DBUG_RETURN(ha_tokudb_exts);
} }
static inline bool is_insert_ignore (THD* thd) {
//
// from http://lists.mysql.com/internals/37735
//
return thd->lex->ignore && thd->lex->duplicates == DUP_ERROR;
}
static inline bool is_replace_into(THD* thd) {
return (thd_sql_command(thd) == SQLCOM_REPLACE) ||
(thd_sql_command(thd) == SQLCOM_REPLACE_SELECT);
}
static inline bool do_ignore_flag_optimization(THD* thd, TABLE* table, uint curr_num_DBs) {
uint pk_insert_mode = get_pk_insert_mode(thd);
return (
(is_replace_into(thd) || is_insert_ignore(thd)) &&
curr_num_DBs <=1 &&
((!table->triggers && pk_insert_mode < 2) || pk_insert_mode == 0)
);
}
ulonglong ha_tokudb::table_flags() const {
return (table && do_ignore_flag_optimization(ha_thd(),table,table->s->keys + test(hidden_primary_key)) ?
int_table_flags | HA_BINLOG_STMT_CAPABLE :
int_table_flags | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE);
}
// //
// Returns a bit mask of capabilities of the key or its part specified by // Returns a bit mask of capabilities of the key or its part specified by
// the arguments. The capabilities are defined in sql/handler.h. // the arguments. The capabilities are defined in sql/handler.h.
...@@ -1091,7 +1119,7 @@ ha_tokudb::ha_tokudb(handlerton * hton, TABLE_SHARE * table_arg):handler(hton, t ...@@ -1091,7 +1119,7 @@ ha_tokudb::ha_tokudb(handlerton * hton, TABLE_SHARE * table_arg):handler(hton, t
// flags defined in sql\handler.h // flags defined in sql\handler.h
{ {
int_table_flags = HA_REC_NOT_IN_SEQ | HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_PRIMARY_KEY_IN_READ_INDEX | int_table_flags = HA_REC_NOT_IN_SEQ | HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_PRIMARY_KEY_IN_READ_INDEX |
HA_FILE_BASED | HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX |HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE; HA_FILE_BASED | HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX;
alloc_ptr = NULL; alloc_ptr = NULL;
rec_buff = NULL; rec_buff = NULL;
transaction = NULL; transaction = NULL;
...@@ -1429,13 +1457,6 @@ int initialize_key_and_col_info(TABLE_SHARE* table_share, TABLE* table, KEY_AND_ ...@@ -1429,13 +1457,6 @@ int initialize_key_and_col_info(TABLE_SHARE* table_share, TABLE* table, KEY_AND_
return error; return error;
} }
static bool is_insert_ignore (THD* thd) {
//
// from http://lists.mysql.com/internals/37735
//
return thd->lex->ignore && thd->lex->duplicates == DUP_ERROR;
}
int ha_tokudb::initialize_share( int ha_tokudb::initialize_share(
const char* name, const char* name,
...@@ -3024,18 +3045,15 @@ int ha_tokudb::insert_row_to_main_dictionary(uchar* record, DBT* pk_key, DBT* pk ...@@ -3024,18 +3045,15 @@ int ha_tokudb::insert_row_to_main_dictionary(uchar* record, DBT* pk_key, DBT* pk
int error; int error;
u_int32_t put_flags; u_int32_t put_flags;
THD *thd = ha_thd(); THD *thd = ha_thd();
bool is_replace_into;
uint curr_num_DBs = table->s->keys + test(hidden_primary_key); uint curr_num_DBs = table->s->keys + test(hidden_primary_key);
ulonglong wait_lock_time = get_write_lock_wait_time(thd); ulonglong wait_lock_time = get_write_lock_wait_time(thd);
bool do_ignore_opt = do_ignore_flag_optimization(thd,table,curr_num_DBs);
assert(curr_num_DBs == 1); assert(curr_num_DBs == 1);
is_replace_into = (thd_sql_command(thd) == SQLCOM_REPLACE) ||
(thd_sql_command(thd) == SQLCOM_REPLACE_SELECT);
put_flags = hidden_primary_key ? DB_YESOVERWRITE : DB_NOOVERWRITE; put_flags = hidden_primary_key ? DB_YESOVERWRITE : DB_NOOVERWRITE;
// //
// optimization for "REPLACE INTO..." command // optimization for "REPLACE INTO..." (and "INSERT IGNORE") command
// if the command is "REPLACE INTO" and the only table // if the command is "REPLACE INTO" and the only table
// is the main table, then we can simply insert the element // is the main table, then we can simply insert the element
// with DB_YESOVERWRITE. If the element does not exist, // with DB_YESOVERWRITE. If the element does not exist,
...@@ -3044,11 +3062,19 @@ int ha_tokudb::insert_row_to_main_dictionary(uchar* record, DBT* pk_key, DBT* pk ...@@ -3044,11 +3062,19 @@ int ha_tokudb::insert_row_to_main_dictionary(uchar* record, DBT* pk_key, DBT* pk
// to do. We cannot do this if curr_num_DBs > 1, because then we lose // to do. We cannot do this if curr_num_DBs > 1, because then we lose
// consistency between indexes // consistency between indexes
// //
if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS) || is_replace_into) { if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS) &&
!is_replace_into(thd) &&
!is_insert_ignore(thd))
{
printf("yes overwrite due to unique checks");
put_flags = DB_YESOVERWRITE; // original put_flags can only be DB_YESOVERWRITE or DB_NOOVERWRITE put_flags = DB_YESOVERWRITE; // original put_flags can only be DB_YESOVERWRITE or DB_NOOVERWRITE
} }
else if (do_ignore_opt && is_replace_into(thd)) {
if (is_insert_ignore(thd)) { printf("doing replace into opt!\n");
put_flags = DB_YESOVERWRITE; // original put_flags can only be DB_YESOVERWRITE or DB_NOOVERWRITE
}
else if (do_ignore_opt && is_insert_ignore(thd)) {
printf("doing insert ignore opt!\n");
put_flags = DB_NOOVERWRITE_NO_ERROR; put_flags = DB_NOOVERWRITE_NO_ERROR;
} }
...@@ -3074,13 +3100,12 @@ int ha_tokudb::insert_row_to_main_dictionary(uchar* record, DBT* pk_key, DBT* pk ...@@ -3074,13 +3100,12 @@ int ha_tokudb::insert_row_to_main_dictionary(uchar* record, DBT* pk_key, DBT* pk
int ha_tokudb::insert_rows_to_dictionaries_mult(DBT* pk_key, DBT* pk_val, DB_TXN* txn, THD* thd) { int ha_tokudb::insert_rows_to_dictionaries_mult(DBT* pk_key, DBT* pk_val, DB_TXN* txn, THD* thd) {
int error; int error;
bool is_replace_into; bool is_replace;
uint curr_num_DBs = table->s->keys + test(hidden_primary_key); uint curr_num_DBs = table->s->keys + test(hidden_primary_key);
ulonglong wait_lock_time = get_write_lock_wait_time(thd); ulonglong wait_lock_time = get_write_lock_wait_time(thd);
is_replace_into = (thd_sql_command(thd) == SQLCOM_REPLACE) || is_replace = is_replace_into(thd);
(thd_sql_command(thd) == SQLCOM_REPLACE_SELECT);
if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS) && !is_replace_into) { if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS) && !is_replace && !is_insert_ignore(thd)) {
share->mult_put_flags[primary_key] = DB_YESOVERWRITE; share->mult_put_flags[primary_key] = DB_YESOVERWRITE;
} }
else { else {
...@@ -3133,8 +3158,6 @@ int ha_tokudb::write_row(uchar * record) { ...@@ -3133,8 +3158,6 @@ int ha_tokudb::write_row(uchar * record) {
tokudb_trx_data *trx = NULL; tokudb_trx_data *trx = NULL;
uint curr_num_DBs = table->s->keys + test(hidden_primary_key); uint curr_num_DBs = table->s->keys + test(hidden_primary_key);
bool create_sub_trans = false; bool create_sub_trans = false;
bool is_replace_into = (thd_sql_command(thd) == SQLCOM_REPLACE) ||
(thd_sql_command(thd) == SQLCOM_REPLACE_SELECT);
// //
// some crap that needs to be done because MySQL does not properly abstract // some crap that needs to be done because MySQL does not properly abstract
...@@ -3190,7 +3213,7 @@ int ha_tokudb::write_row(uchar * record) { ...@@ -3190,7 +3213,7 @@ int ha_tokudb::write_row(uchar * record) {
goto cleanup; goto cleanup;
} }
create_sub_trans = (using_ignore && !(is_replace_into && curr_num_DBs == 1)); create_sub_trans = (using_ignore && !(do_ignore_flag_optimization(thd,table,curr_num_DBs)));
if (create_sub_trans) { if (create_sub_trans) {
error = db_env->txn_begin(db_env, transaction, &sub_trans, DB_INHERIT_ISOLATION); error = db_env->txn_begin(db_env, transaction, &sub_trans, DB_INHERIT_ISOLATION);
if (error) { if (error) {
......
...@@ -321,9 +321,8 @@ class ha_tokudb : public handler { ...@@ -321,9 +321,8 @@ class ha_tokudb : public handler {
// Returns a bit mask of capabilities of storage engine. Capabilities // Returns a bit mask of capabilities of storage engine. Capabilities
// defined in sql/handler.h // defined in sql/handler.h
// //
ulonglong table_flags(void) const { ulonglong table_flags(void) const;
return int_table_flags;
}
ulong index_flags(uint inx, uint part, bool all_parts) const; ulong index_flags(uint inx, uint part, bool all_parts) const;
// //
......
...@@ -72,6 +72,16 @@ static MYSQL_THDVAR_ULONGLONG(read_lock_wait, ...@@ -72,6 +72,16 @@ static MYSQL_THDVAR_ULONGLONG(read_lock_wait,
ULONGLONG_MAX, // max ULONGLONG_MAX, // max
1 // blocksize 1 // blocksize
); );
static MYSQL_THDVAR_UINT(pk_insert_mode,
0,
"set the primary key insert mode",
NULL,
NULL,
1, // default
0, // min?
2, // max
1 // blocksize
);
static void tokudb_print_error(const DB_ENV * db_env, const char *db_errpfx, const char *buffer); static void tokudb_print_error(const DB_ENV * db_env, const char *db_errpfx, const char *buffer);
...@@ -464,6 +474,10 @@ ulonglong get_read_lock_wait_time (THD* thd) { ...@@ -464,6 +474,10 @@ ulonglong get_read_lock_wait_time (THD* thd) {
return (ret_val == 0) ? ULONGLONG_MAX : ret_val; return (ret_val == 0) ? ULONGLONG_MAX : ret_val;
} }
uint get_pk_insert_mode(THD* thd) {
return THDVAR(thd, pk_insert_mode);
}
typedef struct txn_progress_info { typedef struct txn_progress_info {
char status[200]; char status[200];
...@@ -1105,6 +1119,7 @@ static struct st_mysql_sys_var *tokudb_system_variables[] = { ...@@ -1105,6 +1119,7 @@ static struct st_mysql_sys_var *tokudb_system_variables[] = {
MYSQL_SYSVAR(commit_sync), MYSQL_SYSVAR(commit_sync),
MYSQL_SYSVAR(write_lock_wait), MYSQL_SYSVAR(write_lock_wait),
MYSQL_SYSVAR(read_lock_wait), MYSQL_SYSVAR(read_lock_wait),
MYSQL_SYSVAR(pk_insert_mode),
MYSQL_SYSVAR(version), MYSQL_SYSVAR(version),
MYSQL_SYSVAR(init_flags), MYSQL_SYSVAR(init_flags),
MYSQL_SYSVAR(checkpointing_period), MYSQL_SYSVAR(checkpointing_period),
......
...@@ -13,6 +13,7 @@ extern DB *metadata_db; ...@@ -13,6 +13,7 @@ extern DB *metadata_db;
// thread variables // thread variables
ulonglong get_write_lock_wait_time (THD* thd); ulonglong get_write_lock_wait_time (THD* thd);
ulonglong get_read_lock_wait_time (THD* thd); ulonglong get_read_lock_wait_time (THD* thd);
uint get_pk_insert_mode(THD* thd);
extern HASH tokudb_open_tables; extern HASH tokudb_open_tables;
extern pthread_mutex_t tokudb_mutex; extern pthread_mutex_t tokudb_mutex;
......
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