diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result old mode 100755 new mode 100644 index ce8270ae563..37c9da25aeb --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -723,7 +723,6 @@ WHERE int_nokey IN (SELECT it2.int_key FROM it1 LEFT JOIN it2 ON it2.datetime_key); int_key 0 -8 2 0 7 @@ -734,10 +733,11 @@ int_key 0 0 0 -0 3 7 7 +8 +0 5 EXPLAIN SELECT int_key FROM ot1 diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index c64fd110996..1e5026214fd 100755 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -747,7 +747,7 @@ ulong JOIN_CACHE::get_max_join_buffer_size() if (join_tab->join_buffer_size_limit) set_if_smaller(limit_sz, join_tab->join_buffer_size_limit); if (limit_sz / max_records > space_per_record) - max_sz*= space_per_record * max_records; + max_sz= space_per_record * max_records; else max_sz= limit_sz; max_sz+= pack_length_with_blob_ptrs; @@ -790,15 +790,18 @@ int JOIN_CACHE::alloc_buffer() { JOIN_TAB *tab; JOIN_CACHE *cache; + uint i= join->const_tables; ulonglong curr_buff_space_sz= 0; ulonglong curr_min_buff_space_sz= 0; ulonglong join_buff_space_limit= - join->thd->variables.join_buff_space_limit; + join->thd->variables.join_buff_space_limit; + double partial_join_cardinality= (join_tab-1)->get_partial_join_cardinality(); buff= NULL; min_buff_size= 0; max_buff_size= 0; min_records= 1; - max_records= join_tab->records; + max_records= partial_join_cardinality <= join_buff_space_limit ? + (ulonglong) partial_join_cardinality : join_buff_space_limit; set_if_bigger(max_records, 1); min_buff_size= get_min_join_buffer_size(); buff_size= get_max_join_buffer_size(); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b30dc81d7d9..7ccbd8689a9 100755 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7720,6 +7720,9 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) setup_semijoin_dups_elimination(join, options, no_jbuf_after)) DBUG_RETURN(TRUE); /* purecov: inspected */ + for (i= 0; i < join->const_tables; i++) + join->join_tab[i].partial_join_cardinality= 1; + for (i=join->const_tables ; i < join->tables ; i++) { JOIN_TAB *tab=join->join_tab+i; @@ -7731,6 +7734,16 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) tab->next_select=sub_select; /* normal select */ tab->sorted= sorted; sorted= 0; // only first must be sorted + + /* + The approximation below for partial join cardinality is not good because + - it does not take into account some pushdown predicates + - it does not differentiate between inner joins, outer joins and semi-joins. + Later it should be improved. + */ + tab->partial_join_cardinality= join->best_positions[i].records_read * + (i ? (tab-1)->partial_join_cardinality : 1); + if (tab->loosescan_match_tab) { if (!(tab->loosescan_buf= (uchar*)join->thd->alloc(tab-> diff --git a/sql/sql_select.h b/sql/sql_select.h index 251a3869d8c..b78603ca9ca 100755 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -216,7 +216,9 @@ typedef struct st_join_table { E(#records) is in found_records. */ ha_rows read_time; - + + double partial_join_cardinality; + table_map dependent,key_dependent; uint use_quick,index; uint status; ///< Save status for cache @@ -386,6 +388,7 @@ typedef struct st_join_table { calc_used_field_length(TRUE); return max_used_fieldlength; } + double get_partial_join_cardinality() { return partial_join_cardinality; } } JOIN_TAB;