42
42
#include "drizzled/join_cache.h"
43
43
#include "drizzled/show.h"
44
44
#include "drizzled/field/blob.h"
45
#include "drizzled/optimizer/position.h"
46
#include "drizzled/optimizer/sargable_param.h"
45
47
#include "mysys/my_bit.h"
47
49
#include <algorithm>
49
51
using namespace std;
52
using namespace drizzled;
51
54
/** Declarations of static functions used in this source file. */
52
55
static bool make_group_fields(JOIN *main_join, JOIN *curr_join);
53
56
static void calc_group_buffer(JOIN *join,order_st *group);
54
57
static bool alloc_group_fields(JOIN *join,order_st *group);
56
TODO: 'find_best' is here only temporarily until 'greedy_search' is
59
static bool find_best(JOIN *join,table_map rest_tables,uint32_t index, double record_count,double read_time);
60
58
static uint32_t cache_record_length(JOIN *join, uint32_t index);
61
59
static double prev_record_reads(JOIN *join, uint32_t idx, table_map found_ref);
62
60
static bool get_best_combination(JOIN *join);
3019
- TODO: this function is here only temporarily until 'greedy_search' is
3020
tested and accepted.
3026
static bool find_best(JOIN *join,table_map rest_tables,uint32_t idx,double record_count, double read_time)
3028
Session *session= join->session;
3029
Position partial_pos;
3030
if (session->killed)
3037
read_time+= record_count/(double) TIME_FOR_COMPARE;
3038
partial_pos= join->getPosFromPartialPlan(join->const_tables);
3039
if (join->sort_by_table &&
3040
join->sort_by_table !=
3041
partial_pos.table->table)
3043
read_time+= record_count; // We have to make a temp table
3045
if (read_time < join->best_read)
3047
join->copyPartialPlanIntoOptimalPlan(idx);
3048
join->best_read= read_time - 0.001;
3052
if (read_time+record_count/(double) TIME_FOR_COMPARE >= join->best_read)
3054
return false; /* Found better before */
3058
double best_record_count= DBL_MAX;
3059
double best_read_time= DBL_MAX;
3060
for (JoinTable **pos= join->best_ref+idx ; (s= *pos) ; pos++)
3062
table_map real_table_bit= s->table->map;
3065
partial_pos= join->getPosFromPartialPlan(idx - 1);
3067
if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent) &&
3068
(! idx || ! check_interleaving_with_nj(partial_pos.table, s)))
3070
double records, best;
3071
best_access_path(join, s, session, rest_tables, idx, record_count,
3073
partial_pos= join->getPosFromPartialPlan(idx);
3074
records= partial_pos.records_read;
3075
best= partial_pos.read_time;
3077
Go to the next level only if there hasn't been a better key on
3078
this level! This will cut down the search for a lot simple cases!
3080
double current_record_count= record_count * records;
3081
double current_read_time= read_time + best;
3082
if (best_record_count > current_record_count ||
3083
best_read_time > current_read_time ||
3084
(idx == join->const_tables && s->table == join->sort_by_table))
3086
if (best_record_count >= current_record_count &&
3087
best_read_time >= current_read_time &&
3088
(! (s->key_dependent & rest_tables) ||
3089
partial_pos.isConstTable()))
3091
best_record_count= current_record_count;
3092
best_read_time= current_read_time;
3094
std::swap(join->best_ref[idx], *pos);
3095
if (find_best(join,rest_tables & ~real_table_bit,idx+1,
3096
current_record_count,current_read_time))
3100
std::swap(join->best_ref[idx], *pos);
3102
restore_prev_nj_state(s);
3103
if (join->select_options & SELECT_STRAIGHT_JOIN)
3104
break; // Don't test all combinations
3110
3015
static uint32_t cache_record_length(JOIN *join,uint32_t idx)
3112
3017
uint32_t length=0;
3178
3083
static double prev_record_reads(JOIN *join, uint32_t idx, table_map found_ref)
3180
3085
double found=1.0;
3181
Position *pos_end= join->getSpecificPosInPartialPlan(-1);
3182
for (Position *pos= join->getSpecificPosInPartialPlan(idx - 1);
3086
optimizer::Position *pos_end= join->getSpecificPosInPartialPlan(-1);
3087
for (optimizer::Position *pos= join->getSpecificPosInPartialPlan(idx - 1);
3183
3088
pos != pos_end;
3186
if (pos->table->table->map & found_ref)
3091
if (pos->examinePosition(found_ref))
3188
found_ref|= pos->ref_depend_map;
3093
found_ref|= pos->getRefDependMap();
3190
3095
For the case of "t1 LEFT JOIN t2 ON ..." where t2 is a const table
3191
3096
with no matching row we will get position[t2].records_read==0.
3267
3172
/** Save const tables first as used tables. */
3268
3173
static void set_position(JOIN *join,uint32_t idx,JoinTable *table,KeyUse *key)
3271
tmp_pos.table= table;
3273
tmp_pos.records_read= 1.0; /* This is a const table */
3274
tmp_pos.ref_depend_map= 0;
3175
optimizer::Position tmp_pos(1.0, /* This is a const table */
3275
3180
join->setPosInPartialPlan(idx, tmp_pos);
3277
3182
/* Move the const table as down as possible in best_ref */
3336
if (search_depth == MAX_TABLES+2)
3338
TODO: 'MAX_TABLES+2' denotes the old implementation of find_best before
3339
the greedy version. Will be removed when greedy_search is approved.
3341
join->best_read= DBL_MAX;
3342
if (find_best(join, join_tables, join->const_tables, 1.0, 0.0))
3347
if (search_depth == 0)
3348
/* Automatically determine a reasonable value for 'search_depth' */
3349
search_depth= determine_search_depth(join);
3350
if (greedy_search(join, join_tables, search_depth, prune_level))
3237
if (search_depth == 0)
3238
/* Automatically determine a reasonable value for 'search_depth' */
3239
search_depth= determine_search_depth(join);
3240
if (greedy_search(join, join_tables, search_depth, prune_level))
3932
3820
record_count, read_time);
3933
3821
/* compute the cost of the new plan extended with 's' */
3934
3822
partial_pos= join->getPosFromPartialPlan(idx);
3935
record_count*= partial_pos.records_read;
3936
read_time+= partial_pos.read_time;
3823
record_count*= partial_pos.getFanout();
3824
read_time+= partial_pos.getCost();
3937
3825
join_tables&= ~(s->table->map);
3941
3829
read_time+= record_count / (double) TIME_FOR_COMPARE;
3942
3830
partial_pos= join->getPosFromPartialPlan(join->const_tables);
3943
3831
if (join->sort_by_table &&
3944
join->sort_by_table != partial_pos.table->table)
3832
partial_pos.hasTableForSorting(join->sort_by_table))
3945
3833
read_time+= record_count; // We have to make a temp table
3946
3834
join->copyPartialPlanIntoOptimalPlan(idx);
3947
3835
join->best_read= read_time;
4079
3967
std::swap(join->best_ref[idx], join->best_ref[best_idx]);
4081
3969
/* compute the cost of the new plan extended with 'best_table' */
4082
Position partial_pos= join->getPosFromPartialPlan(idx);
4083
record_count*= partial_pos.records_read;
4084
read_time+= partial_pos.read_time;
3970
optimizer::Position partial_pos= join->getPosFromPartialPlan(idx);
3971
record_count*= partial_pos.getFanout();
3972
read_time+= partial_pos.getCost();
4086
3974
remaining_tables&= ~(best_table->table->map);
4235
4123
partial_pos= join->getPosFromPartialPlan(idx - 1);
4237
4125
if ((remaining_tables & real_table_bit) &&
4238
!(remaining_tables & s->dependent) &&
4239
(!idx || !check_interleaving_with_nj(partial_pos.table, s)))
4126
! (remaining_tables & s->dependent) &&
4127
(! idx || ! check_interleaving_with_nj(partial_pos.getJoinTable(), s)))
4241
4129
double current_record_count, current_read_time;
4252
4140
record_count, read_time);
4253
4141
/* Compute the cost of extending the plan with 's' */
4254
4142
partial_pos= join->getPosFromPartialPlan(idx);
4255
current_record_count= record_count * partial_pos.records_read;
4256
current_read_time= read_time + partial_pos.read_time;
4143
current_record_count= record_count * partial_pos.getFanout();
4144
current_read_time= read_time + partial_pos.getCost();
4258
4146
/* Expand only partial plans with lower cost than the best QEP so far */
4259
4147
if ((current_read_time +
4311
4199
partial_pos= join->getPosFromPartialPlan(join->const_tables);
4312
4200
current_read_time+= current_record_count / (double) TIME_FOR_COMPARE;
4313
4201
if (join->sort_by_table &&
4314
join->sort_by_table !=
4315
partial_pos.table->table)
4202
partial_pos.hasTableForSorting(join->sort_by_table))
4316
4203
/* We have to make a temp table */
4317
4204
current_read_time+= current_record_count;
4318
4205
if ((search_depth == 1) || (current_read_time < join->best_read))
4717
4604
cur_pos= join->getPosFromOptimalPlan(i);
4718
4605
if ((cond && (! ((tab->keys & tab->const_keys) == tab->keys) && i > 0)) ||
4719
4606
(! tab->const_keys.none() && (i == join->const_tables) &&
4720
(join->unit->select_limit_cnt < cur_pos.records_read) && ((join->select_options & OPTION_FOUND_ROWS) == false)))
4607
(join->unit->select_limit_cnt < cur_pos.getFanout()) && ((join->select_options & OPTION_FOUND_ROWS) == false)))
4722
4609
/* Join with outer join condition */
4723
4610
COND *orig_cond= sel->cond;
5632
5519
JoinTable *stat,*stat_end,*s,**stat_ref;
5633
5520
KeyUse *keyuse,*start_keyuse;
5634
5521
table_map outer_join=0;
5635
SARGABLE_PARAM *sargables= 0;
5522
vector<optimizer::SargableParam> sargables;
5636
5523
JoinTable *stat_vector[MAX_TABLES+1];
5637
Position *partial_pos;
5524
optimizer::Position *partial_pos;
5639
5526
table_count=join->tables;
5640
5527
stat=(JoinTable*) join->session->calloc(sizeof(JoinTable)*table_count);
5760
5647
if (conds || outer_join)
5761
5648
if (update_ref_and_keys(join->session, keyuse_array, stat, join->tables,
5762
5649
conds, join->cond_equal,
5763
~outer_join, join->select_lex, &sargables))
5650
~outer_join, join->select_lex, sargables))
5766
5653
/* Read tables with 0 or 1 rows (system tables) */
5767
5654
join->const_table_map= 0;
5769
Position *p_pos= join->getFirstPosInPartialPlan();
5770
Position *p_end= join->getSpecificPosInPartialPlan(const_count);
5656
optimizer::Position *p_pos= join->getFirstPosInPartialPlan();
5657
optimizer::Position *p_end= join->getSpecificPosInPartialPlan(const_count);
5771
5658
while (p_pos < p_end)
5661
s= p_pos->getJoinTable();
5775
5662
s->type= AM_SYSTEM;
5776
5663
join->const_table_map|=s->table->map;
5777
5664
if ((tmp= join_read_const_table(s, p_pos)))
5923
5810
Update info on indexes that can be used for search lookups as
5924
5811
reading const tables may has added new sargable predicates.
5926
if (const_count && sargables)
5813
if (const_count && ! sargables.empty())
5928
for( ; sargables->field ; sargables++)
5815
vector<optimizer::SargableParam>::iterator iter= sargables.begin();
5816
while (iter != sargables.end())
5930
Field *field= sargables->field;
5818
Field *field= (*iter).getField();
5931
5819
JoinTable *join_tab= field->table->reginfo.join_tab;
5932
5820
key_map possible_keys= field->key_start;
5933
5821
possible_keys&= field->table->keys_in_use_for_query;
5935
for (uint32_t j=0; j < sargables->num_values; j++)
5936
is_const&= sargables->arg_value[j]->const_item();
5822
bool is_const= true;
5823
for (uint32_t j= 0; j < (*iter).getNumValues(); j++)
5824
is_const&= (*iter).isConstItem(j);
5938
5826
join_tab[0].const_keys|= possible_keys;