1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-30 11:22:14 +03:00

Fix of LEFT JOIN optimizer bug, problem with key cache on Windows and

a lot of portability issues.
This commit is contained in:
monty@donna.mysql.com
2000-10-14 03:16:35 +03:00
parent 5134b08422
commit 7ac13c89e6
48 changed files with 773 additions and 327 deletions

View File

@@ -399,6 +399,11 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
}
if (join.const_tables && !thd->locked_tables)
mysql_unlock_some_tables(thd, join.table,join.const_tables);
if (!conds && join.outer_join)
{
/* Handle the case where we have an OUTER JOIN without a WHERE */
conds=new Item_int((longlong) 1,1); // Always true
}
select=make_select(*join.table, join.const_table_map,
join.const_table_map,conds,&error);
if (error)
@@ -856,6 +861,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
}
}
stat_vector[i]=0;
join->outer_join=outer_join;
/*
** If outer join: Re-arrange tables in stat_vector so that outer join
@@ -1553,12 +1559,14 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
double best,best_time,records;
best=best_time=records=DBL_MAX;
KEYUSE *best_key=0;
uint best_max_key_part=0;
if (s->keyuse)
{ /* Use key if possible */
TABLE *table=s->table;
KEYUSE *keyuse,*start_key=0;
double best_records=DBL_MAX;
uint max_key_part=0;
/* Test how we can use keys */
rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE; /* Assumed records/key */
@@ -1576,34 +1584,34 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
uint keypart=keyuse->keypart;
do
{
if(!ft_key)
if (!ft_key)
{
table_map map;
if (!(rest_tables & keyuse->used_tables))
{
found_part|= (key_part_map) 1 << keypart;
found_ref|= keyuse->used_tables;
}
/*
** If we find a ref, assume this table matches a proportional
** part of this table.
** For example 100 records matching this table with 5000 records
** gives 5000/100 = 50 records per key
** Constant tables are ignored and to avoid bad matches,
** we don't make rec less than 100.
*/
if (keyuse->used_tables &
(map=(keyuse->used_tables & ~join->const_table_map)))
{
uint tablenr;
for (tablenr=0 ; ! (map & 1) ; map>>=1, tablenr++) ;
if (map == 1) // Only one table
table_map map;
if (!(rest_tables & keyuse->used_tables))
{
TABLE *tmp_table=join->all_tables[tablenr];
if (rec > tmp_table->file->records && rec > 100)
rec=max(tmp_table->file->records,100);
found_part|= (key_part_map) 1 << keypart;
found_ref|= keyuse->used_tables;
}
/*
** If we find a ref, assume this table matches a proportional
** part of this table.
** For example 100 records matching a table with 5000 records
** gives 5000/100 = 50 records per key
** Constant tables are ignored and to avoid bad matches,
** we don't make rec less than 100.
*/
if (keyuse->used_tables &
(map=(keyuse->used_tables & ~join->const_table_map)))
{
uint tablenr;
for (tablenr=0 ; ! (map & 1) ; map>>=1, tablenr++) ;
if (map == 1) // Only one table
{
TABLE *tmp_table=join->all_tables[tablenr];
if (rec > tmp_table->file->records && rec > 100)
rec=max(tmp_table->file->records,100);
}
}
}
}
keyuse++;
} while (keyuse->table == table && keyuse->key == key &&
@@ -1637,6 +1645,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
*/
if (found_part == PREV_BITS(uint,keyinfo->key_parts))
{ /* use eq key */
max_key_part= (uint) ~0;
if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
{
tmp=prev_record_reads(join,found_ref);
@@ -1686,7 +1695,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
if ((found_part & 1) &&
!(table->file->option_flag() & HA_ONLY_WHOLE_INDEX))
{
uint max_key_part=max_part_bit(found_part);
max_key_part=max_part_bit(found_part);
/* Check if quick_range could determinate how many rows we
will match */
@@ -1754,11 +1763,19 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
best=tmp;
best_records=records;
best_key=start_key;
best_max_key_part=max_key_part;
}
}
records=best_records;
}
if (records >= s->found_records || best > s->read_time)
/*
Don't test table scan if it can't be better.
Prefer key lookup if we would use the same key for scanning.
*/
if ((records >= s->found_records || best > s->read_time) &&
!(s->quick && best_key && s->quick->index == best_key->key &&
best_max_key_part >= s->table->quick_key_parts[best_key->key]))
{ // Check full join
if (s->on_expr)
{
@@ -1775,6 +1792,10 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
(tmp + record_count/(double) TIME_FOR_COMPARE*s->found_records <
best + record_count/(double) TIME_FOR_COMPARE*records))
{
/*
If the table has a range (s->quick is set) make_join_select()
will ensure that this will be used
*/
best=tmp;
records=s->found_records;
best_key=0;
@@ -2193,6 +2214,14 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
table_map current_map= tab->table->map;
used_tables|=current_map;
COND *tmp=make_cond_for_table(cond,used_tables,current_map);
if (!tmp && tab->quick)
{ // Outer join
/*
Hack to handle the case where we only refer to a table
in the ON part of an OUTER JOIN.
*/
tmp=new Item_int((longlong) 1,1); // Always true
}
if (tmp)
{
DBUG_EXECUTE("where",print_where(tmp,tab->table->table_name););
@@ -2204,6 +2233,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
sel->head=tab->table;
if (tab->quick)
{
/* Use quick key read if it's a constant and it's not used
with key reading */
if (tab->needed_reg == 0 && tab->type != JT_EQ_REF &&
(tab->type != JT_REF ||
(uint) tab->ref.key == tab->quick->index))
@@ -2231,19 +2262,23 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
DBUG_RETURN(1); // Impossible range
/*
We plan to scan all rows.
Check again if we should use an index instead if
we could have used an column from a previous table in
the index or if we are using limit and this is the first table
Check again if we should use an index.
We could have used an column from a previous table in
the index if we are using limit and this is the first table
*/
if ((tab->keys & ~ tab->const_keys && i > 0) ||
tab->const_keys && i == join->const_tables &&
join->thd->select_limit < join->best_positions[i].records_read)
{
/* Join with outer join condition */
COND *orig_cond=sel->cond;
sel->cond=and_conds(sel->cond,tab->on_expr);
if (sel->test_quick_select(tab->keys,
used_tables & ~ current_map,
join->thd->select_limit) < 0)
DBUG_RETURN(1); // Impossible range
DBUG_RETURN(1); // Impossible range
sel->cond=orig_cond;
}
else
{