From: Date: October 20 2007 6:05pm Subject: bk commit into 5.2 tree (sergefp:1.2588) List-Archive: http://lists.mysql.com/commits/36006 Message-Id: <20071020160508.EB2FE14C58B@foxhole.localdomain> Below is the list of changes that have just been committed into a local 5.2 repository of psergey. When psergey does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet@stripped, 2007-10-20 20:05:00+04:00, sergefp@stripped +4 -0 WL#2771 Batched Key Access: - Quick hack implementation of BKA + semi-join FirstMatch strategy sql/handler.cc@stripped, 2007-10-20 20:04:55+04:00, sergefp@stripped +40 -32 WL#2771 Batched Key Access: - Quick hack implementation of BKA + semi-join FirstMatch strategy sql/handler.h@stripped, 2007-10-20 20:04:55+04:00, sergefp@stripped +16 -0 WL#2771 Batched Key Access: - Quick hack implementation of BKA + semi-join FirstMatch strategy sql/sql_select.cc@stripped, 2007-10-20 20:04:55+04:00, sergefp@stripped +20 -6 WL#2771 Batched Key Access: - Quick hack implementation of BKA + semi-join FirstMatch strategy sql/sql_select.h@stripped, 2007-10-20 20:04:55+04:00, sergefp@stripped +18 -7 WL#2771 Batched Key Access: - Quick hack implementation of BKA + semi-join FirstMatch strategy diff -Nrup a/sql/handler.cc b/sql/handler.cc --- a/sql/handler.cc 2007-08-27 02:38:28 +04:00 +++ b/sql/handler.cc 2007-10-20 20:04:55 +04:00 @@ -3457,6 +3457,8 @@ int DsMrr_impl::dsmrr_init(handler *h, K rowids_buf += key->key_length + h->ref_length; is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION); + semi_join= test(mode & HA_MRR_SEMI_JOIN); + DBUG_ASSERT(!semi_join || is_mrr_assoc); rowids_buf_end= buf->buffer_end; elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*); @@ -3572,15 +3574,18 @@ int DsMrr_impl::dsmrr_fill_buffer(handle while ((rowids_buf_cur < rowids_buf_end) && !(res= h->handler::multi_range_read_next(&range_info))) { - /* Put rowid, or {rowid, range_id} pair into the buffer */ - h->position(h->table->record[0]); - memcpy(rowids_buf_cur, h->ref, h->ref_length); - rowids_buf_cur += h->ref_length; - - if (is_mrr_assoc) + if (!semi_join || *range_info==0) { - memcpy(rowids_buf_cur, &range_info, sizeof(void*)); - rowids_buf_cur += sizeof(void*); + /* Put rowid, or {rowid, range_id} pair into the buffer */ + h->position(h->table->record[0]); + memcpy(rowids_buf_cur, h->ref, h->ref_length); + rowids_buf_cur += h->ref_length; + + if (is_mrr_assoc) + { + memcpy(rowids_buf_cur, &range_info, sizeof(void*)); + rowids_buf_cur += sizeof(void*); + } } } @@ -3607,40 +3612,43 @@ int DsMrr_impl::dsmrr_fill_buffer(handle int DsMrr_impl::dsmrr_next(handler *h, char **range_info) { int res; + uchar *cur_rowid; if (use_default_impl) return h->handler::multi_range_read_next(range_info); - if (rowids_buf_cur == rowids_buf_last) + do { - h->table->column_bitmaps_set_no_signal(save_read_set, save_write_set); - if (dsmrr_eof) + if (rowids_buf_cur == rowids_buf_last) + { + h->table->column_bitmaps_set_no_signal(save_read_set, save_write_set); + if (dsmrr_eof) + { + res= HA_ERR_END_OF_FILE; + goto end; + } + + res= dsmrr_fill_buffer(h); + h->table->column_bitmaps_set_no_signal(&row_access_bitmap, + &row_access_bitmap); + if (res) + goto end; + } + + /* Return EOF if there are no rowids in the buffer after re-fill attempt */ + if (rowids_buf_cur == rowids_buf_last) { res= HA_ERR_END_OF_FILE; goto end; } - - res= dsmrr_fill_buffer(h); - h->table->column_bitmaps_set_no_signal(&row_access_bitmap, - &row_access_bitmap); - if (res) - goto end; - } - - /* Return EOF if there are no rowids in the buffer after re-fill attempt */ - if (rowids_buf_cur == rowids_buf_last) - { - res= HA_ERR_END_OF_FILE; - goto end; - } - - res= h2->rnd_pos(h->table->record[0], rowids_buf_cur); - rowids_buf_cur += h->ref_length; + cur_rowid= rowids_buf_cur; + rowids_buf_cur += h->ref_length + sizeof(void*) * test(is_mrr_assoc); + + } while (semi_join && *(cur_rowid + h->ref_length)==0); + + res= h2->rnd_pos(h->table->record[0], cur_rowid); if (is_mrr_assoc) - { - memcpy(range_info, rowids_buf_cur, sizeof(void*)); - rowids_buf_cur += sizeof(void*); - } + memcpy(range_info, cur_rowid + h->ref_length, sizeof(void*)); end: if (res) diff -Nrup a/sql/handler.h b/sql/handler.h --- a/sql/handler.h 2007-10-03 15:09:44 +04:00 +++ b/sql/handler.h 2007-10-20 20:04:55 +04:00 @@ -1091,6 +1091,16 @@ void get_sweep_read_cost(TABLE *table, h */ #define HA_MRR_NO_NULL_ENDPOINTS 128 +/* + Flag set <=> We're running a first-match semi-join, and the accessed table + is the inner table. + MRR implementation may (but doesn't have to) interpret KEY_MULTI_RANGE::ptr + as char* need_no_more_matches, if "*need_no_more_matches=1" then the SQL + layer does not need any more records from this range. + + HA_MRR_SEMI_JOIN cannot be used together with HA_MRR_NO_ASSOCIATION. +*/ +#define HA_MRR_SEMI_JOIN 256 class ha_statistics { @@ -2064,6 +2074,12 @@ public: /* TRUE <=> need range association, buffer holds {rowid, range_id} pairs */ bool is_mrr_assoc; + + /* + TRUE <=> doing a first-match semi-join, check if we need any more records in + the scanned range + */ + bool semi_join; handler *h; /* Owner table handler */ handler *h2; /* Slave handler for doing rnd_pos(). */ diff -Nrup a/sql/sql_select.cc b/sql/sql_select.cc --- a/sql/sql_select.cc 2007-10-19 02:46:41 +04:00 +++ b/sql/sql_select.cc 2007-10-20 20:04:55 +04:00 @@ -1073,7 +1073,10 @@ int setup_semijoin_dups_elimination(JOIN { if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) && tab->type == JT_ALL && tab->use_quick != 2 && !tab->first_inner && - i <= no_jbuf_after && !dealing_with_jbuf) + i <= no_jbuf_after && !dealing_with_jbuf && + emb_sj_map != tab->table->map) + // ^ psergey-add: and there is more than one inner table in the + // SJ-nest { /* This table uses join buffering, which makes use of FirstMatch or @@ -13356,6 +13359,7 @@ evaluate_join_record(JOIN *join, JOIN_TA enumerated all the suffixes for current prefix row combination */ return_tab= join_tab->do_firstmatch; + join_tab->found= 1; //psergey-add: } /* @@ -13520,9 +13524,12 @@ JOIN_CACHE_BNL::join_records(bool skip_l for (i= records - (skip_last ? 1 : 0) ; i-- > 0 ;) { get_record(); - if (!join_tab->select || !join_tab->select->skip_record()) + if ((!join_tab->select || !join_tab->select->skip_record()) && + (!(join_tab->emb_sj_nest->sj_inner_tables == join_tab->table->map && + join_tab->do_firstmatch == join_tab - 1) || !get_match_flag())) { int res= 0; + set_match_flag(1); if (!join_tab->check_weed_out_table || !(res= do_sj_dups_weedout(join->thd, join_tab->check_weed_out_table))) @@ -16596,7 +16603,7 @@ static uint bka_range_seq_next(range_seq start_key->flag= HA_READ_KEY_EXACT; range->end_key= *start_key; range->end_key.flag= HA_READ_AFTER_KEY; - range->ptr= (char *) cache->get_record_label(); + range->ptr= (char *) cache->get_record_pos(); range->range_flag= EQ_RANGE; DBUG_RETURN(0); } @@ -16676,8 +16683,12 @@ JOIN_CACHE_BKA::join_records(bool skip_l init_mrr_buff(); if (!file->inited) file->ha_index_init(join_tab->ref.key, 1); + uint mrr_mode= 0; + if (join_tab->emb_sj_nest->sj_inner_tables == join_tab->table->map && + join_tab->do_firstmatch == join_tab - 1) + mrr_mode= HA_MRR_SEMI_JOIN; error= file->multi_range_read_init(&seq_funcs, (void*)this, records, - 0, &mrr_buff); + mrr_mode, &mrr_buff); for (JOIN_TAB *tmp=join->join_tab; tmp != join_tab ; tmp++) { @@ -16694,10 +16705,13 @@ JOIN_CACHE_BKA::join_records(bool skip_l } if (rc == NESTED_LOOP_OK) { - get_record(rec_ptr); - if (!join_tab->select || !join_tab->select->skip_record()) + get_record_by_pos(rec_ptr); + if ((!join_tab->select || !join_tab->select->skip_record()) && + (!(join_tab->emb_sj_nest->sj_inner_tables == join_tab->table->map && + join_tab->do_firstmatch == join_tab - 1) || !get_match_flag())) { int res= 0; + set_match_flag(1); if (!join_tab->check_weed_out_table || !(res= do_sj_dups_weedout(join->thd, join_tab->check_weed_out_table))) diff -Nrup a/sql/sql_select.h b/sql/sql_select.h --- a/sql/sql_select.h 2007-10-19 02:27:45 +04:00 +++ b/sql/sql_select.h 2007-10-20 20:04:55 +04:00 @@ -315,6 +315,7 @@ protected: { return length; } virtual uint addon_length() { return 0; } + uchar *rec_pos; public: JOIN_TAB *join_tab; virtual ~JOIN_CACHE() {} @@ -335,6 +336,17 @@ public: virtual bool put_record()= 0; virtual bool get_record()= 0; virtual enum_nested_loop_state join_records(bool skip_last)= 0; + virtual uchar *get_record_pos() + { + return rec_pos; + } + + /* + Getter/setter for "there were matches" flag. + The said flag is the 1st byte of the cached record + */ + bool get_match_flag() { return test(*get_record_pos()); } + void set_match_flag(bool set) { (*get_record_pos())= (uchar)set; } }; class JOIN_CACHE_BNL :public JOIN_CACHE @@ -352,14 +364,16 @@ public: return is_full; } bool get_record() - { return read_record_data() == 0; } + { + rec_pos= pos; + return read_record_data() == 0; + } enum_nested_loop_state join_records(bool skip_last); }; class JOIN_CACHE_BKA :public JOIN_CACHE { protected: - uchar *rec_pos; uint key_arg_fields; HANDLER_BUFFER mrr_buff; public: @@ -404,10 +418,6 @@ public: rec_pos= pos; return read_record_data() == 0; } - virtual uchar *get_record_label() - { - return rec_pos; - } bool is_key_access() { return TRUE; } int init() { @@ -426,11 +436,12 @@ public: end_pos= end; } virtual uint get_next_key(uchar **key); - virtual void get_record(uchar *rec_ptr) + virtual void get_record_by_pos(uchar *rec_ptr) { uchar *save_pos= pos; uint save_record_nr= record_nr; pos= rec_ptr; + rec_pos= pos; record_nr= 0; read_record_data(); pos= save_pos;