Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
d89166cd
Commit
d89166cd
authored
Jan 18, 2005
by
sergefp@mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge spetrunia@bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/home/psergey/mysql-5.0-fix-vg1
parents
4aebc4b3
1eab462c
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
187 additions
and
174 deletions
+187
-174
include/my_bitmap.h
include/my_bitmap.h
+1
-1
mysql-test/r/index_merge_innodb.result
mysql-test/r/index_merge_innodb.result
+1
-1
mysql-test/r/index_merge_ror_cpk.result
mysql-test/r/index_merge_ror_cpk.result
+1
-1
mysql-test/t/index_merge_innodb.test
mysql-test/t/index_merge_innodb.test
+1
-1
sql/opt_range.cc
sql/opt_range.cc
+183
-170
No files found.
include/my_bitmap.h
View file @
d89166cd
...
...
@@ -24,7 +24,7 @@
typedef
struct
st_bitmap
{
uchar
*
bitmap
;
uint
bitmap_size
;
uint
bitmap_size
;
/* number of bytes occupied by the above */
/*
mutex will be acquired for the duration of each bitmap operation if
thread_safe flag in bitmap_init was set. Otherwise, we optimize by not
...
...
mysql-test/r/index_merge_innodb.result
View file @
d89166cd
drop table if exists t1;
drop table if exists t1
,t2
;
create table t1
(
key1 int not null,
...
...
mysql-test/r/index_merge_ror_cpk.result
View file @
d89166cd
...
...
@@ -26,7 +26,7 @@ primary key (pk1, pk2)
) engine=innodb;
explain select * from t1 where pk1 = 1 and pk2 < 80 and key1=0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 r
ef PRIMARY,key1 PRIMARY 4 const 1
Using where
1 SIMPLE t1 r
ange PRIMARY,key1 PRIMARY 8 NULL 9
Using where
select * from t1 where pk1 = 1 and pk2 < 80 and key1=0;
pk1 pk2 key1 key2 pktail1ok pktail2ok pktail3bad pktail4bad pktail5bad pk2copy badkey filler1 filler2
1 10 0 0 0 0 0 0 0 10 0 filler-data-10 filler2
...
...
mysql-test/t/index_merge_innodb.test
View file @
d89166cd
...
...
@@ -4,7 +4,7 @@
--
source
include
/
have_innodb
.
inc
--
disable_warnings
drop
table
if
exists
t1
;
drop
table
if
exists
t1
,
t2
;
--
enable_warnings
create
table
t1
...
...
sql/opt_range.cc
View file @
d89166cd
...
...
@@ -50,6 +50,11 @@
#define test_use_count(A) {}
#endif
/*
Convert double value to #rows. Currently this does floor(), and we
might consider using round() instead.
*/
#define double2rows(x) ((ha_rows)(x))
static
int
sel_cmp
(
Field
*
f
,
char
*
a
,
char
*
b
,
uint8
a_flag
,
uint8
b_flag
);
...
...
@@ -1628,6 +1633,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
DBUG_PRINT
(
"enter"
,(
"keys_to_use: %lu prev_tables: %lu const_tables: %lu"
,
keys_to_use
.
to_ulonglong
(),
(
ulong
)
prev_tables
,
(
ulong
)
const_tables
));
DBUG_PRINT
(
"info"
,
(
"records=%lu"
,
(
ulong
)
head
->
file
->
records
));
delete
quick
;
quick
=
0
;
needed_reg
.
clear_all
();
...
...
@@ -1874,6 +1880,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
double
get_sweep_read_cost
(
const
PARAM
*
param
,
ha_rows
records
)
{
double
result
;
DBUG_ENTER
(
"get_sweep_read_cost"
);
if
(
param
->
table
->
file
->
primary_key_is_clustered
())
{
result
=
param
->
table
->
file
->
read_time
(
param
->
table
->
s
->
primary_key
,
...
...
@@ -1912,7 +1919,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records)
}
}
DBUG_PRINT
(
"info"
,(
"returning cost=%g"
,
result
));
return
result
;
DBUG_RETURN
(
result
)
;
}
...
...
@@ -2393,43 +2400,27 @@ typedef struct
{
const
PARAM
*
param
;
MY_BITMAP
covered_fields
;
/* union of fields covered by all scans */
/* TRUE if covered_fields is a superset of needed_fields */
bool
is_covering
;
double
index_scan_costs
;
/* SUM(cost of 'index-only' scans) */
double
total_cost
;
/*
Fraction of table records that satisfies conditions of all scans.
This is the number of full records that will be retrieved if a
non-index_only index intersection will be employed.
*/
double
records_fract
;
double
out_rows
;
/* TRUE if covered_fields is a superset of needed_fields */
bool
is_covering
;
ha_rows
index_records
;
/* sum(#records to look in indexes) */
double
index_scan_costs
;
/* SUM(cost of 'index-only' scans) */
double
total_cost
;
}
ROR_INTERSECT_INFO
;
/*
Re-initialize an allocated intersect info to contain zero scans.
SYNOPSIS
info Intersection info structure to re-initialize.
*/
static
void
ror_intersect_reinit
(
ROR_INTERSECT_INFO
*
info
)
{
info
->
is_covering
=
FALSE
;
info
->
index_scan_costs
=
0.0
f
;
info
->
records_fract
=
1.0
f
;
bitmap_clear_all
(
&
info
->
covered_fields
);
}
/*
Allocate a ROR_INTERSECT_INFO and initialize it to contain zero scans.
SYNOPSIS
ror_intersect_init()
param Parameter from test_quick_select
is_index_only If TRUE, set ROR_INTERSECT_INFO to be covering
RETURN
allocated structure
...
...
@@ -2437,7 +2428,7 @@ static void ror_intersect_reinit(ROR_INTERSECT_INFO *info)
*/
static
ROR_INTERSECT_INFO
*
ror_intersect_init
(
const
PARAM
*
param
,
bool
is_index_only
)
ROR_INTERSECT_INFO
*
ror_intersect_init
(
const
PARAM
*
param
)
{
ROR_INTERSECT_INFO
*
info
;
uchar
*
buf
;
...
...
@@ -2450,46 +2441,39 @@ ROR_INTERSECT_INFO* ror_intersect_init(const PARAM *param, bool is_index_only)
if
(
bitmap_init
(
&
info
->
covered_fields
,
buf
,
param
->
fields_bitmap_size
*
8
,
FALSE
))
return
NULL
;
ror_intersect_reinit
(
info
);
info
->
is_covering
=
FALSE
;
info
->
index_scan_costs
=
0.0
;
info
->
index_records
=
0
;
info
->
out_rows
=
param
->
table
->
file
->
records
;
bitmap_clear_all
(
&
info
->
covered_fields
);
return
info
;
}
void
ror_intersect_cpy
(
ROR_INTERSECT_INFO
*
dst
,
const
ROR_INTERSECT_INFO
*
src
)
{
dst
->
param
=
src
->
param
;
memcpy
(
dst
->
covered_fields
.
bitmap
,
src
->
covered_fields
.
bitmap
,
src
->
covered_fields
.
bitmap_size
);
dst
->
out_rows
=
src
->
out_rows
;
dst
->
is_covering
=
src
->
is_covering
;
dst
->
index_records
=
src
->
index_records
;
dst
->
index_scan_costs
=
src
->
index_scan_costs
;
dst
->
total_cost
=
src
->
total_cost
;
}
/*
Check if adding a ROR scan to a ROR-intersection reduces its cost of
ROR-intersection and if yes, update parameters of ROR-intersection,
including its cost.
Get selectivity of a ROR scan wrt ROR-intersection.
SYNOPSIS
ror_intersect_add()
param Parameter from test_quick_select
info ROR-intersection structure to add the scan to.
ror_scan ROR scan info to add.
is_cpk_scan If TRUE, add the scan as CPK scan (this can be inferred
from other parameters and is passed separately only to
avoid duplicating the inference code)
ror_scan_selectivity()
info ROR-interection
scan ROR scan
NOTES
Adding a ROR scan to ROR-intersect "makes sense" iff the cost of ROR-
intersection decreases. The cost of ROR-intersection is caclulated as
follows:
cost= SUM_i(key_scan_cost_i) + cost_of_full_rows_retrieval
if (union of indexes used covers all needed fields)
cost_of_full_rows_retrieval= 0;
else
{
cost_of_full_rows_retrieval=
cost_of_sweep_read(E(rows_to_retrieve), rows_in_table);
}
E(rows_to_retrieve) is caclulated as follows:
Suppose we have a condition on several keys
cond=k_11=c_11 AND k_12=c_12 AND ... // parts of first key
k_21=c_21 AND k_22=c_22 AND ... // parts of second key
...
k_n1=c_n1 AND k_n3=c_n3 AND ... (1)
k_n1=c_n1 AND k_n3=c_n3 AND ... (1)
//parts of the key used by *scan
where k_ij may be the same as any k_pq (i.e. keys may have common parts).
...
...
@@ -2563,38 +2547,30 @@ ROR_INTERSECT_INFO* ror_intersect_init(const PARAM *param, bool is_index_only)
and reduce adjacent fractions.
RETURN
TRUE ROR scan added to ROR-intersection, cost updated
.
FALSE It doesn't make sense to add this ROR scan to this ROR-intersection.
Selectivity of given ROR scan
.
*/
bool
ror_intersect_add
(
const
PARAM
*
param
,
ROR_INTERSECT_INFO
*
info
,
ROR_SCAN_INFO
*
ror_scan
,
bool
is_cpk_scan
=
FALSE
)
static
double
ror_scan_selectivity
(
const
ROR_INTERSECT_INFO
*
info
,
const
ROR_SCAN_INFO
*
scan
)
{
int
i
;
SEL_ARG
*
sel_arg
;
KEY_PART_INFO
*
key_part
=
info
->
param
->
table
->
key_info
[
ror_scan
->
keynr
].
key_part
;
double
selectivity_mult
=
1.0
;
KEY_PART_INFO
*
key_part
=
info
->
param
->
table
->
key_info
[
scan
->
keynr
].
key_part
;
byte
key_val
[
MAX_KEY_LENGTH
+
MAX_FIELD_WIDTH
];
/* key values tuple */
DBUG_ENTER
(
"ror_intersect_add"
);
DBUG_PRINT
(
"info"
,
(
"Current selectivity= %g"
,
info
->
records_fract
));
DBUG_PRINT
(
"info"
,
(
"Adding scan on %s"
,
info
->
param
->
table
->
key_info
[
ror_scan
->
keynr
].
name
));
SEL_ARG
*
tuple_arg
=
NULL
;
char
*
key_ptr
=
(
char
*
)
key_val
;
bool
cur_covered
,
prev_covered
=
bitmap_is_set
(
&
info
->
covered_fields
,
key_part
->
fieldnr
);
ha_rows
prev_records
=
param
->
table
->
file
->
records
;
SEL_ARG
*
sel_arg
,
*
tuple_arg
=
NULL
;
bool
cur_covered
;
bool
prev_covered
=
bitmap_is_set
(
&
info
->
covered_fields
,
key_part
->
fieldnr
);
key_range
min_range
;
key_range
max_range
;
min_range
.
key
=
(
byte
*
)
key_val
;
min_range
.
flag
=
HA_READ_KEY_EXACT
;
max_range
.
key
=
(
byte
*
)
key_val
;
max_range
.
flag
=
HA_READ_AFTER_KEY
;
for
(
i
=
0
,
sel_arg
=
ror_scan
->
sel_arg
;
sel_arg
;
ha_rows
prev_records
=
info
->
param
->
table
->
file
->
records
;
int
i
;
DBUG_ENTER
(
"ror_intersect_selectivity"
);
for
(
i
=
0
,
sel_arg
=
scan
->
sel_arg
;
sel_arg
;
i
++
,
sel_arg
=
sel_arg
->
next_key_part
)
{
cur_covered
=
bitmap_is_set
(
&
info
->
covered_fields
,
(
key_part
+
i
)
->
fieldnr
);
...
...
@@ -2604,7 +2580,7 @@ bool ror_intersect_add(const PARAM *param, ROR_INTERSECT_INFO *info,
{
if
(
!
tuple_arg
)
{
tuple_arg
=
ror_
scan
->
sel_arg
;
tuple_arg
=
scan
->
sel_arg
;
tuple_arg
->
store_min
(
key_part
->
length
,
&
key_ptr
,
0
);
}
while
(
tuple_arg
->
next_key_part
!=
sel_arg
)
...
...
@@ -2615,10 +2591,8 @@ bool ror_intersect_add(const PARAM *param, ROR_INTERSECT_INFO *info,
}
ha_rows
records
;
min_range
.
length
=
max_range
.
length
=
((
char
*
)
key_ptr
-
(
char
*
)
key_val
);
records
=
param
->
table
->
file
->
records_in_range
(
ror_scan
->
keynr
,
&
min_range
,
&
max_range
);
records
=
info
->
param
->
table
->
file
->
records_in_range
(
scan
->
keynr
,
&
min_range
,
&
max_range
);
if
(
cur_covered
)
{
/* uncovered -> covered */
...
...
@@ -2637,49 +2611,105 @@ bool ror_intersect_add(const PARAM *param, ROR_INTERSECT_INFO *info,
}
if
(
!
prev_covered
)
{
double
tmp
=
rows2double
(
param
->
table
->
quick_rows
[
ror_
scan
->
keynr
])
/
double
tmp
=
rows2double
(
info
->
param
->
table
->
quick_rows
[
scan
->
keynr
])
/
rows2double
(
prev_records
);
DBUG_PRINT
(
"info"
,
(
"Selectivity multiplier: %g"
,
tmp
));
selectivity_mult
*=
tmp
;
}
DBUG_PRINT
(
"info"
,
(
"Returning multiplier: %g"
,
selectivity_mult
));
DBUG_RETURN
(
selectivity_mult
);
}
/*
Check if adding a ROR scan to a ROR-intersection reduces its cost of
ROR-intersection and if yes, update parameters of ROR-intersection,
including its cost.
SYNOPSIS
ror_intersect_add()
param Parameter from test_quick_select
info ROR-intersection structure to add the scan to.
ror_scan ROR scan info to add.
is_cpk_scan If TRUE, add the scan as CPK scan (this can be inferred
from other parameters and is passed separately only to
avoid duplicating the inference code)
NOTES
Adding a ROR scan to ROR-intersect "makes sense" iff the cost of ROR-
intersection decreases. The cost of ROR-intersection is calculated as
follows:
cost= SUM_i(key_scan_cost_i) + cost_of_full_rows_retrieval
When we add a scan the first increases and the second decreases.
cost_of_full_rows_retrieval=
(union of indexes used covers all needed fields) ?
cost_of_sweep_read(E(rows_to_retrieve), rows_in_table) :
0
E(rows_to_retrieve) = #rows_in_table * ror_scan_selectivity(null, scan1) *
ror_scan_selectivity({scan1}, scan2) * ... *
ror_scan_selectivity({scan1,...}, scanN).
RETURN
TRUE ROR scan added to ROR-intersection, cost updated.
FALSE It doesn't make sense to add this ROR scan to this ROR-intersection.
*/
static
bool
ror_intersect_add
(
ROR_INTERSECT_INFO
*
info
,
ROR_SCAN_INFO
*
ror_scan
,
bool
is_cpk_scan
)
{
double
selectivity_mult
=
1.0
;
DBUG_ENTER
(
"ror_intersect_add"
);
DBUG_PRINT
(
"info"
,
(
"Current out_rows= %g"
,
info
->
out_rows
));
DBUG_PRINT
(
"info"
,
(
"Adding scan on %s"
,
info
->
param
->
table
->
key_info
[
ror_scan
->
keynr
].
name
));
DBUG_PRINT
(
"info"
,
(
"is_cpk_scan=%d"
,
is_cpk_scan
));
selectivity_mult
=
ror_scan_selectivity
(
info
,
ror_scan
);
if
(
selectivity_mult
==
1.0
)
{
/* Don't add this scan if it doesn't improve selectivity. */
DBUG_PRINT
(
"info"
,
(
"The scan doesn't improve selectivity."
));
DBUG_RETURN
(
FALSE
);
DBUG_RETURN
(
false
);
}
info
->
records_fract
*=
selectivity_mult
;
ha_rows
cur_scan_records
=
info
->
param
->
table
->
quick_rows
[
ror_scan
->
keynr
];
info
->
out_rows
*=
selectivity_mult
;
DBUG_PRINT
(
"info"
,
(
"info->total_cost= %g"
,
info
->
total_cost
));
if
(
is_cpk_scan
)
{
info
->
index_scan_costs
+=
rows2double
(
cur_scan_records
)
*
/*
CPK scan is used to filter out rows. We apply filtering for
each record of every scan. Assuming 1/TIME_FOR_COMPARE_ROWID
per check this gives us:
*/
info
->
index_scan_costs
+=
rows2double
(
info
->
index_records
)
/
TIME_FOR_COMPARE_ROWID
;
}
else
{
info
->
index_records
+=
cur_scan_records
;
info
->
index_records
+=
info
->
param
->
table
->
quick_rows
[
ror_scan
->
keynr
]
;
info
->
index_scan_costs
+=
ror_scan
->
index_read_cost
;
bitmap_union
(
&
info
->
covered_fields
,
&
ror_scan
->
covered_fields
);
}
if
(
!
info
->
is_covering
&&
bitmap_is_subset
(
&
info
->
param
->
needed_fields
,
&
info
->
covered_fields
))
{
DBUG_PRINT
(
"info"
,
(
"ROR-intersect is covering now"
));
info
->
is_covering
=
TRUE
;
if
(
!
info
->
is_covering
&&
bitmap_is_subset
(
&
info
->
param
->
needed_fields
,
&
info
->
covered_fields
))
{
DBUG_PRINT
(
"info"
,
(
"ROR-intersect is covering now"
));
info
->
is_covering
=
TRUE
;
}
}
info
->
total_cost
=
info
->
index_scan_costs
;
DBUG_PRINT
(
"info"
,
(
"info->total_cost= %g"
,
info
->
total_cost
));
if
(
!
info
->
is_covering
)
{
ha_rows
table_recs
=
info
->
param
->
table
->
file
->
records
;
info
->
total_cost
+=
get_sweep_read_cost
(
info
->
param
,
(
ha_rows
)(
info
->
records_fract
*
table_recs
));
info
->
total_cost
+=
get_sweep_read_cost
(
info
->
param
,
double2rows
(
info
->
out_rows
));
DBUG_PRINT
(
"info"
,
(
"info->total_cost= %g"
,
info
->
total_cost
));
}
DBUG_PRINT
(
"info"
,
(
"New
selectivity= %g"
,
info
->
records_fract
));
DBUG_PRINT
(
"info"
,
(
"New
out_rows= %g"
,
info
->
out_rows
));
DBUG_PRINT
(
"info"
,
(
"New cost= %g, %scovering"
,
info
->
total_cost
,
info
->
is_covering
?
""
:
"non-"
));
DBUG_RETURN
(
TRUE
);
...
...
@@ -2701,9 +2731,13 @@ bool ror_intersect_add(const PARAM *param, ROR_INTERSECT_INFO *info,
a covering ROR-intersection)
NOTES
get_key_scans_params must be called before for the same SEL_TREE before
this function can be called.
get_key_scans_params must be called before this function can be called.
When this function is called by ROR-union construction algorithm it
assumes it is building an uncovered ROR-intersection (and thus # of full
records to be retrieved is wrong here). This is a hack.
IMPLEMENTATION
The approximate best non-covering plan search algorithm is as follows:
find_min_ror_intersection_scan()
...
...
@@ -2717,11 +2751,11 @@ bool ror_intersect_add(const PARAM *param, ROR_INTERSECT_INFO *info,
min_scan= make_scan(S);
while (R is not empty)
{
if (!selectivity(S + first(R) < selectivity(S)))
firstR= R - first(R);
if (!selectivity(S + firstR < selectivity(S)))
continue;
S= S + first(R);
R= R - first(R);
if (cost(S) < min_cost)
{
min_cost= cost(S);
...
...
@@ -2752,15 +2786,15 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
bool
*
are_all_covering
)
{
uint
idx
;
double
min_cost
=
read_time
;
double
min_cost
=
DBL_MAX
;
DBUG_ENTER
(
"get_best_ror_intersect"
);
if
((
tree
->
n_ror_scans
<
2
)
||
!
param
->
table
->
file
->
records
)
DBUG_RETURN
(
NULL
);
/*
Collect ROR-able SEL_ARGs and create ROR_SCAN_INFO for each of them.
Also find and save clustered PK scan if there is one.
Step1: Collect ROR-able SEL_ARGs and create ROR_SCAN_INFO for each of
them.
Also find and save clustered PK scan if there is one.
*/
ROR_SCAN_INFO
**
cur_ror_scan
;
ROR_SCAN_INFO
*
cpk_scan
=
NULL
;
...
...
@@ -2796,8 +2830,8 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
tree
->
ror_scans_end
););
/*
Ok, [ror_scans, ror_scans_end) is array of ptrs to initialized
ROR_SCAN_INFOs.
Now, get a minimal key sca
n using an approximate algorithm.
ROR_SCAN_INFO
'
s.
Step 2: Get best ROR-intersectio
n using an approximate algorithm.
*/
qsort
(
tree
->
ror_scans
,
tree
->
n_ror_scans
,
sizeof
(
ROR_SCAN_INFO
*
),
(
qsort_cmp
)
cmp_ror_scan_info
);
...
...
@@ -2814,45 +2848,41 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
intersect_scans_end
=
intersect_scans
;
/* Create and incrementally update ROR intersection. */
ROR_INTERSECT_INFO
*
intersect
;
if
(
!
(
intersect
=
ror_intersect_init
(
param
,
FALSE
)))
ROR_INTERSECT_INFO
*
intersect
,
*
intersect_best
;
if
(
!
(
intersect
=
ror_intersect_init
(
param
))
||
!
(
intersect_best
=
ror_intersect_init
(
param
)))
return
NULL
;
/* [intersect_scans,
intersect_scans_best) will hold the best combina
tion */
/* [intersect_scans,
intersect_scans_best) will hold the best intersec
tion */
ROR_SCAN_INFO
**
intersect_scans_best
;
ha_rows
best_rows
;
bool
is_best_covering
;
double
best_index_scan_costs
;
LINT_INIT
(
best_rows
);
/* protected by intersect_scans_best */
LINT_INIT
(
is_best_covering
);
LINT_INIT
(
best_index_scan_costs
);
cur_ror_scan
=
tree
->
ror_scans
;
/* Start with one scan */
intersect_scans_best
=
intersect_scans
;
while
(
cur_ror_scan
!=
tree
->
ror_scans_end
&&
!
intersect
->
is_covering
)
{
/* S= S + first(R); */
if
(
ror_intersect_add
(
param
,
intersect
,
*
cur_ror_scan
))
*
(
intersect_scans_end
++
)
=
*
cur_ror_scan
;
/* R= R - first(R); */
cur_ror_scan
++
;
/* S= S + first(R); R= R - first(R); */
if
(
!
ror_intersect_add
(
intersect
,
*
cur_ror_scan
,
false
))
{
cur_ror_scan
++
;
continue
;
}
*
(
intersect_scans_end
++
)
=
*
(
cur_ror_scan
++
);
if
(
intersect
->
total_cost
<
min_cost
)
{
/* Local minimum found, save it */
min_cost
=
intersect
->
total_cost
;
best_rows
=
(
ha_rows
)(
intersect
->
records_fract
*
rows2double
(
param
->
table
->
file
->
records
));
/* Prevent divisons by zero */
if
(
!
best_rows
)
best_rows
=
1
;
is_best_covering
=
intersect
->
is_covering
;
ror_intersect_cpy
(
intersect_best
,
intersect
);
intersect_scans_best
=
intersect_scans_end
;
best_index_scan_costs
=
intersect
->
index_scan_costs
;
min_cost
=
intersect
->
total_cost
;
}
}
if
(
intersect_scans_best
==
intersect_scans
)
{
DBUG_PRINT
(
"info"
,
(
"None of scans increase selectivity"
));
DBUG_RETURN
(
NULL
);
}
DBUG_EXECUTE
(
"info"
,
print_ror_scans_arr
(
param
->
table
,
"best ROR-intersection"
,
intersect_scans
,
...
...
@@ -2860,48 +2890,26 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
*
are_all_covering
=
intersect
->
is_covering
;
uint
best_num
=
intersect_scans_best
-
intersect_scans
;
ror_intersect_cpy
(
intersect
,
intersect_best
);
/*
Ok, found the best ROR-intersection of non-CPK key scans.
Check if we should add a CPK scan.
If the obtained ROR-intersection is covering, it doesn't make sense
to add CPK scan - Clustered PK contains all fields and if we're doing
CPK scan doing other CPK scans will only add more overhead.
Check if we should add a CPK scan. If the obtained ROR-intersection is
covering, it doesn't make sense to add CPK scan.
*/
if
(
cpk_scan
&&
!
intersect
->
is_covering
)
{
/*
Handle the special case: ROR-intersect(PRIMARY, key1) is
the best, but cost(range(key1)) > cost(best_non_ror_range_scan)
*/
if
(
best_num
==
0
)
{
cur_ror_scan
=
tree
->
ror_scans
;
intersect_scans_end
=
intersect_scans
;
ror_intersect_reinit
(
intersect
);
if
(
!
ror_intersect_add
(
param
,
intersect
,
*
cur_ror_scan
))
DBUG_RETURN
(
NULL
);
/* shouldn't happen actually */
*
(
intersect_scans_end
++
)
=
*
cur_ror_scan
;
best_num
++
;
}
if
(
ror_intersect_add
(
param
,
intersect
,
cpk_scan
))
if
(
ror_intersect_add
(
intersect
,
cpk_scan
,
TRUE
)
&&
(
intersect
->
total_cost
<
min_cost
))
{
cpk_scan_used
=
TRUE
;
min_cost
=
intersect
->
total_cost
;
best_rows
=
(
ha_rows
)(
intersect
->
records_fract
*
rows2double
(
param
->
table
->
file
->
records
));
/* Prevent divisons by zero */
if
(
!
best_rows
)
best_rows
=
1
;
is_best_covering
=
intersect
->
is_covering
;
best_index_scan_costs
=
intersect
->
index_scan_costs
;
intersect_best
=
intersect
;
//just set pointer here
}
}
/* Ok, return ROR-intersect plan if we have found one */
TRP_ROR_INTERSECT
*
trp
=
NULL
;
if
(
best_num
>
1
||
cpk_scan_used
)
if
(
min_cost
<
read_time
&&
(
cpk_scan_used
||
best_num
>
1
)
)
{
if
(
!
(
trp
=
new
(
param
->
mem_root
)
TRP_ROR_INTERSECT
))
DBUG_RETURN
(
trp
);
...
...
@@ -2911,14 +2919,18 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
DBUG_RETURN
(
NULL
);
memcpy
(
trp
->
first_scan
,
intersect_scans
,
best_num
*
sizeof
(
ROR_SCAN_INFO
*
));
trp
->
last_scan
=
trp
->
first_scan
+
best_num
;
trp
->
is_covering
=
is_best_covering
;
trp
->
read_cost
=
min_cost
;
trp
->
is_covering
=
intersect_best
->
is_covering
;
trp
->
read_cost
=
intersect_best
->
total_cost
;
/* Prevent divisons by zero */
ha_rows
best_rows
=
double2rows
(
intersect_best
->
out_rows
);
if
(
!
best_rows
)
best_rows
=
1
;
trp
->
records
=
best_rows
;
trp
->
index_scan_costs
=
best_
index_scan_costs
;
trp
->
cpk_scan
=
cpk_scan
;
DBUG_PRINT
(
"info"
,
(
"Returning non-covering ROR-intersect plan:
cost %g, records %lu"
,
trp
->
read_cost
,
(
ulong
)
trp
->
records
));
trp
->
index_scan_costs
=
intersect_best
->
index_scan_costs
;
trp
->
cpk_scan
=
cpk_scan
_used
?
cpk_scan
:
NULL
;
DBUG_PRINT
(
"info"
,
(
"Returning non-covering ROR-intersect plan:"
"
cost %g, records %lu"
,
trp
->
read_cost
,
(
ulong
)
trp
->
records
));
}
DBUG_RETURN
(
trp
);
}
...
...
@@ -3145,8 +3157,9 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
found_records
)
+
cpu_cost
;
DBUG_PRINT
(
"info"
,(
"read_time: %g found_read_time: %g"
,
read_time
,
found_read_time
));
DBUG_PRINT
(
"info"
,(
"key %s: found_read_time: %g (cur. read_time: %g)"
,
param
->
table
->
key_info
[
keynr
].
name
,
found_read_time
,
read_time
));
if
(
read_time
>
found_read_time
&&
found_records
!=
HA_POS_ERROR
/*|| read_time == DBL_MAX*/
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment