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
2b79a181
Commit
2b79a181
authored
Dec 21, 2004
by
unknown
Browse files
Options
Browse Files
Download
Plain Diff
Merge joreland@bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/home/jonas/src/mysql-5.0
parents
28bbaf08
272b380b
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
255 additions
and
61 deletions
+255
-61
include/queues.h
include/queues.h
+1
-0
innobase/os/os0proc.c
innobase/os/os0proc.c
+10
-4
mysql-test/r/index_merge.result
mysql-test/r/index_merge.result
+52
-1
mysql-test/r/join_outer.result
mysql-test/r/join_outer.result
+15
-0
mysql-test/t/index_merge.test
mysql-test/t/index_merge.test
+46
-3
mysql-test/t/join_outer.test
mysql-test/t/join_outer.test
+10
-0
sql/opt_range.cc
sql/opt_range.cc
+79
-35
sql/opt_range.h
sql/opt_range.h
+10
-8
sql/sql_select.cc
sql/sql_select.cc
+32
-10
No files found.
include/queues.h
View file @
2b79a181
...
...
@@ -53,6 +53,7 @@ int resize_queue(QUEUE *queue, uint max_elements);
void
delete_queue
(
QUEUE
*
queue
);
void
queue_insert
(
QUEUE
*
queue
,
byte
*
element
);
byte
*
queue_remove
(
QUEUE
*
queue
,
uint
idx
);
#define queue_remove_all(queue) { (queue)->elements= 0; }
void
_downheap
(
QUEUE
*
queue
,
uint
idx
);
void
queue_fix
(
QUEUE
*
queue
);
#define is_queue_inited(queue) ((queue)->root != 0)
...
...
innobase/os/os0proc.c
View file @
2b79a181
...
...
@@ -532,7 +532,7 @@ os_mem_alloc_large(
ibool
assert_on_error
)
/* in: if TRUE, we crash mysqld if the memory
cannot be allocated */
{
#ifdef
UNIV_LINUX
#ifdef
HAVE_LARGE_PAGES
ulint
size
;
int
shmid
;
void
*
ptr
=
NULL
;
...
...
@@ -541,7 +541,8 @@ os_mem_alloc_large(
if
(
!
os_use_large_pages
||
!
os_large_page_size
)
{
goto
skip
;
}
#ifdef UNIV_LINUX
/* Align block size to os_large_page_size */
size
=
((
n
-
1
)
&
~
(
os_large_page_size
-
1
))
+
os_large_page_size
;
...
...
@@ -561,6 +562,7 @@ os_mem_alloc_large(
*/
shmctl
(
shmid
,
IPC_RMID
,
&
buf
);
}
#endif
if
(
ptr
)
{
if
(
set_to_zero
)
{
...
...
@@ -573,8 +575,8 @@ os_mem_alloc_large(
}
fprintf
(
stderr
,
"InnoDB HugeTLB: Warning: Using conventional memory pool
\n
"
);
#endif
skip:
#endif
/* HAVE_LARGE_PAGES */
return
(
ut_malloc_low
(
n
,
set_to_zero
,
assert_on_error
));
}
...
...
@@ -587,8 +589,12 @@ os_mem_free_large(
/*=================*/
void
*
ptr
)
/* in: number of bytes */
{
#ifdef HAVE_LARGE_PAGES
if
(
os_use_large_pages
&&
os_large_page_size
#ifdef UNIV_LINUX
if
(
os_use_large_pages
&&
os_large_page_size
&&
!
shmdt
(
ptr
))
{
&&
!
shmdt
(
ptr
)
#endif
)
{
return
;
}
#endif
...
...
mysql-test/r/index_merge.result
View file @
2b79a181
drop table if exists t0, t1, t2, t3,t4;
drop table if exists t0, t1, t2, t3,
t4;
create table t0
(
key1 int not null,
...
...
@@ -335,4 +335,55 @@ key1 key2 key3 key4 key5 key6 key7 key8
select count(*) from t0;
count(*)
1021
drop table t4;
create table t4 (a int);
insert into t4 values (1),(4),(3);
set @save_join_buffer_size=@@join_buffer_size;
set join_buffer_size= 4000;
show variables like 'join_buffer_size';
Variable_name Value
join_buffer_size 8228
explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
where (A.key1 < 500000 or A.key2 < 3)
and (B.key1 < 500000 or B.key2 < 3);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE A index_merge i1,i2 i1,i2 4,4 NULL 1016 Using sort_union(i1,i2); Using where
1 SIMPLE B index_merge i1,i2 i1,i2 4,4 NULL 1016 Using sort_union(i1,i2); Using where
select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
where (A.key1 < 500000 or A.key2 < 3)
and (B.key1 < 500000 or B.key2 < 3);
max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
10240
update t0 set key1=1;
explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
where (A.key1 = 1 or A.key2 = 1)
and (B.key1 = 1 or B.key2 = 1);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE A index_merge i1,i2 i1,i2 4,4 NULL 1020 Using union(i1,i2); Using where
1 SIMPLE B index_merge i1,i2 i1,i2 4,4 NULL 1020 Using union(i1,i2); Using where
select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
where (A.key1 = 1 or A.key2 = 1)
and (B.key1 = 1 or B.key2 = 1);
max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
8194
alter table t0 add filler1 char(200), add filler2 char(200), add filler3 char(200);
update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500;
explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A, t0 as B
where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)
and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7 = 1 or B.key8=1);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE A index_merge i1,i2,i3,i4,i5,i6,i7,i8 i2,i3,i4,i5,i6,i8 4,4,4,4,4,4 NULL 16 Using union(intersect(i2,i3,i4,i5,i6),i8); Using where
1 SIMPLE B index_merge i1,i2,i3,i4,i5,i6,i7,i8 i2,i3,i4,i5,i6,i8 4,4,4,4,4,4 NULL 16 Using union(intersect(i2,i3,i4,i5,i6),i8); Using where
select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A, t0 as B
where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)
and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7 = 1 or B.key8=1);
max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
8186
set join_buffer_size= @save_join_buffer_size;
drop table t0, t1, t2, t3, t4;
mysql-test/r/join_outer.result
View file @
2b79a181
...
...
@@ -853,4 +853,19 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
1 SIMPLE t2 ALL NULL NULL NULL NULL 2
1 SIMPLE t3 ALL NULL NULL NULL NULL 2
drop table t1,t2;
create table t1 (a int, b int);
insert into t1 values (1,1),(2,2),(3,3);
create table t2 (a int, b int);
insert into t2 values (1,1), (2,2);
select * from t2 right join t1 on t2.a=t1.a;
a b a b
1 1 1 1
2 2 2 2
NULL NULL 3 3
select straight_join * from t2 right join t1 on t2.a=t1.a;
a b a b
1 1 1 1
2 2 2 2
NULL NULL 3 3
DROP TABLE t0,t1,t2,t3;
mysql-test/t/index_merge.test
View file @
2b79a181
#
# Index merge tests
#
--
disable_warnings
drop
table
if
exists
t0
,
t1
,
t2
,
t3
,
t4
;
drop
table
if
exists
t0
,
t1
,
t2
,
t3
,
t4
;
--
enable_warnings
# Create and fill a table with simple keys
...
...
@@ -278,4 +277,48 @@ delete from t0 where key1 < 3 or key2 < 4;
select
*
from
t0
where
key1
<
3
or
key2
<
4
;
select
count
(
*
)
from
t0
;
drop
table
t0
,
t1
,
t2
,
t3
,
t4
;
# Test for BUG#4177
drop
table
t4
;
create
table
t4
(
a
int
);
insert
into
t4
values
(
1
),(
4
),(
3
);
set
@
save_join_buffer_size
=@@
join_buffer_size
;
set
join_buffer_size
=
4000
;
show
variables
like
'join_buffer_size'
;
explain
select
max
(
A
.
key1
+
B
.
key1
+
A
.
key2
+
B
.
key2
+
A
.
key3
+
B
.
key3
+
A
.
key4
+
B
.
key4
+
A
.
key5
+
B
.
key5
)
from
t0
as
A
force
index
(
i1
,
i2
),
t0
as
B
force
index
(
i1
,
i2
)
where
(
A
.
key1
<
500000
or
A
.
key2
<
3
)
and
(
B
.
key1
<
500000
or
B
.
key2
<
3
);
select
max
(
A
.
key1
+
B
.
key1
+
A
.
key2
+
B
.
key2
+
A
.
key3
+
B
.
key3
+
A
.
key4
+
B
.
key4
+
A
.
key5
+
B
.
key5
)
from
t0
as
A
force
index
(
i1
,
i2
),
t0
as
B
force
index
(
i1
,
i2
)
where
(
A
.
key1
<
500000
or
A
.
key2
<
3
)
and
(
B
.
key1
<
500000
or
B
.
key2
<
3
);
update
t0
set
key1
=
1
;
explain
select
max
(
A
.
key1
+
B
.
key1
+
A
.
key2
+
B
.
key2
+
A
.
key3
+
B
.
key3
+
A
.
key4
+
B
.
key4
+
A
.
key5
+
B
.
key5
)
from
t0
as
A
force
index
(
i1
,
i2
),
t0
as
B
force
index
(
i1
,
i2
)
where
(
A
.
key1
=
1
or
A
.
key2
=
1
)
and
(
B
.
key1
=
1
or
B
.
key2
=
1
);
select
max
(
A
.
key1
+
B
.
key1
+
A
.
key2
+
B
.
key2
+
A
.
key3
+
B
.
key3
+
A
.
key4
+
B
.
key4
+
A
.
key5
+
B
.
key5
)
from
t0
as
A
force
index
(
i1
,
i2
),
t0
as
B
force
index
(
i1
,
i2
)
where
(
A
.
key1
=
1
or
A
.
key2
=
1
)
and
(
B
.
key1
=
1
or
B
.
key2
=
1
);
alter
table
t0
add
filler1
char
(
200
),
add
filler2
char
(
200
),
add
filler3
char
(
200
);
update
t0
set
key2
=
1
,
key3
=
1
,
key4
=
1
,
key5
=
1
,
key6
=
1
,
key7
=
1
where
key7
<
500
;
explain
select
max
(
A
.
key1
+
B
.
key1
+
A
.
key2
+
B
.
key2
+
A
.
key3
+
B
.
key3
+
A
.
key4
+
B
.
key4
+
A
.
key5
+
B
.
key5
)
from
t0
as
A
,
t0
as
B
where
(
A
.
key1
=
1
and
A
.
key2
=
1
and
A
.
key3
=
1
and
A
.
key4
=
1
and
A
.
key5
=
1
and
A
.
key6
=
1
and
A
.
key7
=
1
or
A
.
key8
=
1
)
and
(
B
.
key1
=
1
and
B
.
key2
=
1
and
B
.
key3
=
1
and
B
.
key4
=
1
and
B
.
key5
=
1
and
B
.
key6
=
1
and
B
.
key7
=
1
or
B
.
key8
=
1
);
select
max
(
A
.
key1
+
B
.
key1
+
A
.
key2
+
B
.
key2
+
A
.
key3
+
B
.
key3
+
A
.
key4
+
B
.
key4
+
A
.
key5
+
B
.
key5
)
from
t0
as
A
,
t0
as
B
where
(
A
.
key1
=
1
and
A
.
key2
=
1
and
A
.
key3
=
1
and
A
.
key4
=
1
and
A
.
key5
=
1
and
A
.
key6
=
1
and
A
.
key7
=
1
or
A
.
key8
=
1
)
and
(
B
.
key1
=
1
and
B
.
key2
=
1
and
B
.
key3
=
1
and
B
.
key4
=
1
and
B
.
key5
=
1
and
B
.
key6
=
1
and
B
.
key7
=
1
or
B
.
key8
=
1
);
set
join_buffer_size
=
@
save_join_buffer_size
;
# Test for BUG#4177 ends
drop
table
t0
,
t1
,
t2
,
t3
,
t4
;
mysql-test/t/join_outer.test
View file @
2b79a181
...
...
@@ -606,4 +606,14 @@ INSERT INTO t1 VALUES (0);
SELECT
*
FROM
t0
,
t1
LEFT
JOIN
(
t2
,
t3
)
ON
a1
=
5
WHERE
a0
=
a1
AND
a0
=
1
;
EXPLAIN
SELECT
*
FROM
t0
,
t1
LEFT
JOIN
(
t2
,
t3
)
ON
a1
=
5
WHERE
a0
=
a1
AND
a0
=
1
;
# Test for BUG#4480
drop
table
t1
,
t2
;
create
table
t1
(
a
int
,
b
int
);
insert
into
t1
values
(
1
,
1
),(
2
,
2
),(
3
,
3
);
create
table
t2
(
a
int
,
b
int
);
insert
into
t2
values
(
1
,
1
),
(
2
,
2
);
select
*
from
t2
right
join
t1
on
t2
.
a
=
t1
.
a
;
select
straight_join
*
from
t2
right
join
t1
on
t2
.
a
=
t1
.
a
;
DROP
TABLE
t0
,
t1
,
t2
,
t3
;
sql/opt_range.cc
View file @
2b79a181
...
...
@@ -777,8 +777,7 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT()
QUICK_INDEX_MERGE_SELECT
::
QUICK_INDEX_MERGE_SELECT
(
THD
*
thd_param
,
TABLE
*
table
)
:
cur_quick_it
(
quick_selects
),
pk_quick_select
(
NULL
),
unique
(
NULL
),
thd
(
thd_param
)
:
pk_quick_select
(
NULL
),
thd
(
thd_param
)
{
DBUG_ENTER
(
"QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT"
);
index
=
MAX_KEY
;
...
...
@@ -790,17 +789,14 @@ QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param,
int
QUICK_INDEX_MERGE_SELECT
::
init
()
{
cur_quick_it
.
rewind
();
cur_quick_select
=
cur_quick_it
++
;
return
0
;
DBUG_ENTER
(
"QUICK_INDEX_MERGE_SELECT::init"
);
DBUG_RETURN
(
0
);
}
int
QUICK_INDEX_MERGE_SELECT
::
reset
()
{
int
result
;
DBUG_ENTER
(
"QUICK_INDEX_MERGE_SELECT::reset"
);
result
=
cur_quick_select
->
reset
()
||
prepare_unique
();
DBUG_RETURN
(
result
);
DBUG_RETURN
(
read_keys_and_merge
());
}
bool
...
...
@@ -820,8 +816,12 @@ QUICK_INDEX_MERGE_SELECT::push_quick_back(QUICK_RANGE_SELECT *quick_sel_range)
QUICK_INDEX_MERGE_SELECT
::~
QUICK_INDEX_MERGE_SELECT
()
{
List_iterator_fast
<
QUICK_RANGE_SELECT
>
quick_it
(
quick_selects
);
QUICK_RANGE_SELECT
*
quick
;
DBUG_ENTER
(
"QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT"
);
delete
unique
;
quick_it
.
rewind
();
while
((
quick
=
quick_it
++
))
quick
->
file
=
NULL
;
quick_selects
.
delete_elements
();
delete
pk_quick_select
;
free_root
(
&
alloc
,
MYF
(
0
));
...
...
@@ -833,7 +833,8 @@ QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param,
TABLE
*
table
,
bool
retrieve_full_rows
,
MEM_ROOT
*
parent_alloc
)
:
cpk_quick
(
NULL
),
thd
(
thd_param
),
need_to_fetch_row
(
retrieve_full_rows
)
:
cpk_quick
(
NULL
),
thd
(
thd_param
),
need_to_fetch_row
(
retrieve_full_rows
),
scans_inited
(
false
)
{
index
=
MAX_KEY
;
head
=
table
;
...
...
@@ -859,8 +860,9 @@ QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param,
int
QUICK_ROR_INTERSECT_SELECT
::
init
()
{
/* Check if last_rowid was successfully allocated in ctor */
return
!
last_rowid
;
DBUG_ENTER
(
"QUICK_ROR_INTERSECT_SELECT::init"
);
/* Check if last_rowid was successfully allocated in ctor */
DBUG_RETURN
(
!
last_rowid
);
}
...
...
@@ -953,7 +955,7 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
DBUG_ENTER
(
"QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan"
);
/* Initialize all merged "children" quick selects */
DBUG_ASSERT
(
!
(
need_to_fetch_row
&&
!
reuse_handler
)
);
DBUG_ASSERT
(
!
need_to_fetch_row
||
reuse_handler
);
if
(
!
need_to_fetch_row
&&
reuse_handler
)
{
quick
=
quick_it
++
;
...
...
@@ -995,7 +997,14 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
int
QUICK_ROR_INTERSECT_SELECT
::
reset
()
{
DBUG_ENTER
(
"QUICK_ROR_INTERSECT_SELECT::reset"
);
DBUG_RETURN
(
init_ror_merged_scan
(
TRUE
));
if
(
!
scans_inited
&&
init_ror_merged_scan
(
TRUE
))
DBUG_RETURN
(
1
);
scans_inited
=
true
;
List_iterator_fast
<
QUICK_RANGE_SELECT
>
it
(
quick_selects
);
QUICK_RANGE_SELECT
*
quick
;
while
((
quick
=
it
++
))
quick
->
reset
();
DBUG_RETURN
(
0
);
}
...
...
@@ -1034,7 +1043,7 @@ QUICK_ROR_INTERSECT_SELECT::~QUICK_ROR_INTERSECT_SELECT()
QUICK_ROR_UNION_SELECT
::
QUICK_ROR_UNION_SELECT
(
THD
*
thd_param
,
TABLE
*
table
)
:
thd
(
thd_param
)
:
thd
(
thd_param
),
scans_inited
(
false
)
{
index
=
MAX_KEY
;
head
=
table
;
...
...
@@ -1057,18 +1066,19 @@ QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param,
int
QUICK_ROR_UNION_SELECT
::
init
()
{
DBUG_ENTER
(
"QUICK_ROR_UNION_SELECT::init"
);
if
(
init_queue
(
&
queue
,
quick_selects
.
elements
,
0
,
FALSE
,
QUICK_ROR_UNION_SELECT
::
queue_cmp
,
(
void
*
)
this
))
{
bzero
(
&
queue
,
sizeof
(
QUEUE
));
return
1
;
DBUG_RETURN
(
1
)
;
}
if
(
!
(
cur_rowid
=
(
byte
*
)
alloc_root
(
&
alloc
,
2
*
head
->
file
->
ref_length
)))
return
1
;
DBUG_RETURN
(
1
)
;
prev_rowid
=
cur_rowid
+
head
->
file
->
ref_length
;
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -1106,6 +1116,18 @@ int QUICK_ROR_UNION_SELECT::reset()
int
error
;
DBUG_ENTER
(
"QUICK_ROR_UNION_SELECT::reset"
);
have_prev_rowid
=
FALSE
;
if
(
!
scans_inited
)
{
QUICK_SELECT_I
*
quick
;
List_iterator_fast
<
QUICK_SELECT_I
>
it
(
quick_selects
);
while
((
quick
=
it
++
))
{
if
(
quick
->
init_ror_merged_scan
(
FALSE
))
DBUG_RETURN
(
1
);
}
scans_inited
=
true
;
}
queue_remove_all
(
&
queue
);
/*
Initialize scans for merged quick selects and put all merged quick
selects into the queue.
...
...
@@ -1113,7 +1135,7 @@ int QUICK_ROR_UNION_SELECT::reset()
List_iterator_fast
<
QUICK_SELECT_I
>
it
(
quick_selects
);
while
((
quick
=
it
++
))
{
if
(
quick
->
init_ror_merged_scan
(
FALSE
))
if
(
quick
->
reset
(
))
DBUG_RETURN
(
1
);
if
((
error
=
quick
->
get_next
()))
{
...
...
@@ -1591,7 +1613,6 @@ 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
));
delete
quick
;
quick
=
0
;
needed_reg
.
clear_all
();
...
...
@@ -5553,22 +5574,29 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
/*
Fetch all row ids into unique.
Perform key scans for all used indexes (except CPK), get rowids and merge
them into an ordered non-recurrent sequence of rowids.
The merge/duplicate removal is performed using Unique class. We put all
rowids into Unique, get the sorted sequence and destroy the Unique.
If table has a clustered primary key that covers all rows (TRUE for bdb
and innodb currently) and one of the index_merge scans is a scan on PK,
then
primary key scan rowids are not put into Unique and also
rows that will be retrieved by PK scan are not put into Unique
rows that will be retrieved by PK scan are not put into Unique and
primary key scan is not performed here, it is performed later separately.
RETURN
0 OK
other error
*/
int
QUICK_INDEX_MERGE_SELECT
::
prepare_uniqu
e
()
int
QUICK_INDEX_MERGE_SELECT
::
read_keys_and_merg
e
()
{
List_iterator_fast
<
QUICK_RANGE_SELECT
>
cur_quick_it
(
quick_selects
);
QUICK_RANGE_SELECT
*
cur_quick
;
int
result
;
Unique
*
unique
;
DBUG_ENTER
(
"QUICK_INDEX_MERGE_SELECT::prepare_unique"
);
/* We're going to just read rowids. */
...
...
@@ -5583,7 +5611,17 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique()
*/
head
->
file
->
extra
(
HA_EXTRA_RETRIEVE_ALL_COLS
);
cur_quick_select
->
init
();
cur_quick_it
.
rewind
();
cur_quick
=
cur_quick_it
++
;
DBUG_ASSERT
(
cur_quick
);
/*
We reuse the same instance of handler so we need to call both init and
reset here.
*/
if
(
cur_quick
->
init
())
DBUG_RETURN
(
1
);
cur_quick
->
reset
();
unique
=
new
Unique
(
refpos_order_cmp
,
(
void
*
)
head
->
file
,
head
->
file
->
ref_length
,
...
...
@@ -5592,24 +5630,28 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique()
DBUG_RETURN
(
1
);
for
(;;)
{
while
((
result
=
cur_quick
_select
->
get_next
())
==
HA_ERR_END_OF_FILE
)
while
((
result
=
cur_quick
->
get_next
())
==
HA_ERR_END_OF_FILE
)
{
cur_quick
_select
->
range_end
();
cur_quick
_select
=
cur_quick_it
++
;
if
(
!
cur_quick
_select
)
cur_quick
->
range_end
();
cur_quick
=
cur_quick_it
++
;
if
(
!
cur_quick
)
break
;
if
(
cur_quick_select
->
init
())
if
(
cur_quick
->
file
->
inited
!=
handler
::
NONE
)
cur_quick
->
file
->
ha_index_end
();
if
(
cur_quick
->
init
())
DBUG_RETURN
(
1
);
/* QUICK_RANGE_SELECT::reset never fails */
cur_quick
_select
->
reset
();
cur_quick
->
reset
();
}
if
(
result
)
{
if
(
result
!=
HA_ERR_END_OF_FILE
)
{
cur_quick
->
range_end
();
DBUG_RETURN
(
result
);
}
break
;
}
...
...
@@ -5620,8 +5662,8 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique()
if
(
pk_quick_select
&&
pk_quick_select
->
row_in_ranges
())
continue
;
cur_quick
_select
->
file
->
position
(
cur_quick_select
->
record
);
result
=
unique
->
unique_add
((
char
*
)
cur_quick
_select
->
file
->
ref
);
cur_quick
->
file
->
position
(
cur_quick
->
record
);
result
=
unique
->
unique_add
((
char
*
)
cur_quick
->
file
->
ref
);
if
(
result
)
DBUG_RETURN
(
1
);
...
...
@@ -5629,6 +5671,7 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique()
/* ok, all row ids are in Unique */
result
=
unique
->
get
(
head
);
delete
unique
;
doing_pk_scan
=
FALSE
;
/* start table scan */
init_read_record
(
&
read_record
,
thd
,
head
,
(
SQL_SELECT
*
)
0
,
1
,
1
);
...
...
@@ -5668,6 +5711,7 @@ int QUICK_INDEX_MERGE_SELECT::get_next()
doing_pk_scan
=
TRUE
;
if
((
result
=
pk_quick_select
->
init
()))
DBUG_RETURN
(
result
);
pk_quick_select
->
reset
();
DBUG_RETURN
(
pk_quick_select
->
get_next
());
}
}
...
...
sql/opt_range.h
View file @
2b79a181
...
...
@@ -127,7 +127,8 @@ class QUICK_SELECT_I
reset() should be called when it is certain that row retrieval will be
necessary. This call may do heavyweight initialization like buffering first
N records etc. If reset() call fails get_next() must not be called.
Note that reset() may be called several times if this quick select
executes in a subselect.
RETURN
0 OK
other Error code
...
...
@@ -274,6 +275,10 @@ class QUICK_RANGE_SELECT : public QUICK_SELECT_I
next
=
0
;
range
=
NULL
;
cur_range
=
NULL
;
/*
Note: in opt_range.cc there are places where it is assumed that this
function always succeeds
*/
return
0
;
}
int
init
();
...
...
@@ -388,21 +393,15 @@ class QUICK_INDEX_MERGE_SELECT : public QUICK_SELECT_I
/* range quick selects this index_merge read consists of */
List
<
QUICK_RANGE_SELECT
>
quick_selects
;
/* quick select which is currently used for rows retrieval */
List_iterator_fast
<
QUICK_RANGE_SELECT
>
cur_quick_it
;
QUICK_RANGE_SELECT
*
cur_quick_select
;
/* quick select that uses clustered primary key (NULL if none) */
QUICK_RANGE_SELECT
*
pk_quick_select
;
/* true if this select is currently doing a clustered PK scan */
bool
doing_pk_scan
;
Unique
*
unique
;
MEM_ROOT
alloc
;
THD
*
thd
;
int
prepare_uniqu
e
();
int
read_keys_and_merg
e
();
/* used to get rows collected in Unique */
READ_RECORD
read_record
;
...
...
@@ -465,6 +464,8 @@ class QUICK_ROR_INTERSECT_SELECT : public QUICK_SELECT_I
MEM_ROOT
alloc
;
/* Memory pool for this and merged quick selects data. */
THD
*
thd
;
/* current thread */
bool
need_to_fetch_row
;
/* if true, do retrieve full table records. */
/* in top-level quick select, true if merged scans where initialized */
bool
scans_inited
;
};
...
...
@@ -514,6 +515,7 @@ class QUICK_ROR_UNION_SELECT : public QUICK_SELECT_I
uint
rowid_length
;
/* table rowid length */
private:
static
int
queue_cmp
(
void
*
arg
,
byte
*
val1
,
byte
*
val2
);
bool
scans_inited
;
};
...
...
sql/sql_select.cc
View file @
2b79a181
...
...
@@ -64,6 +64,7 @@ static void best_extension_by_limited_search(JOIN *join,
uint
prune_level
);
static
uint
determine_search_depth
(
JOIN
*
join
);
static
int
join_tab_cmp
(
const
void
*
ptr1
,
const
void
*
ptr2
);
static
int
join_tab_cmp_straight
(
const
void
*
ptr1
,
const
void
*
ptr2
);
/*
TODO: 'find_best' is here only temporarily until 'greedy_search' is
tested and approved.
...
...
@@ -3678,22 +3679,26 @@ choose_plan(JOIN *join, table_map join_tables)
{
uint
search_depth
=
join
->
thd
->
variables
.
optimizer_search_depth
;
uint
prune_level
=
join
->
thd
->
variables
.
optimizer_prune_level
;
bool
straight_join
=
join
->
select_options
&
SELECT_STRAIGHT_JOIN
;
DBUG_ENTER
(
"choose_plan"
);
if
(
join
->
select_options
&
SELECT_STRAIGHT_JOIN
)
/*
if (SELECT_STRAIGHT_JOIN option is set)
reorder tables so dependent tables come after tables they depend
on, otherwise keep tables in the order they were specified in the query
else
Apply heuristic: pre-sort all access plans with respect to the number of
records accessed.
*/
qsort
(
join
->
best_ref
+
join
->
const_tables
,
join
->
tables
-
join
->
const_tables
,
sizeof
(
JOIN_TAB
*
),
straight_join
?
join_tab_cmp_straight
:
join_tab_cmp
);
if
(
straight_join
)
{
optimize_straight_join
(
join
,
join_tables
);
}
else
{
/*
Heuristic: pre-sort all access plans with respect to the number of
records accessed.
*/
qsort
(
join
->
best_ref
+
join
->
const_tables
,
join
->
tables
-
join
->
const_tables
,
sizeof
(
JOIN_TAB
*
),
join_tab_cmp
);
if
(
search_depth
==
MAX_TABLES
+
2
)
{
/*
TODO: 'MAX_TABLES+2' denotes the old implementation of find_best before
...
...
@@ -3750,6 +3755,23 @@ join_tab_cmp(const void* ptr1, const void* ptr2)
}
/*
Same as join_tab_cmp, but for use with SELECT_STRAIGHT_JOIN.
*/
static
int
join_tab_cmp_straight
(
const
void
*
ptr1
,
const
void
*
ptr2
)
{
JOIN_TAB
*
jt1
=
*
(
JOIN_TAB
**
)
ptr1
;
JOIN_TAB
*
jt2
=
*
(
JOIN_TAB
**
)
ptr2
;
if
(
jt1
->
dependent
&
jt2
->
table
->
map
)
return
1
;
if
(
jt2
->
dependent
&
jt1
->
table
->
map
)
return
-
1
;
return
jt1
>
jt2
?
1
:
(
jt1
<
jt2
?
-
1
:
0
);
}
/*
Heuristic procedure to automatically guess a reasonable degree of
exhaustiveness for the greedy search procedure.
...
...
@@ -3832,7 +3854,7 @@ optimize_straight_join(JOIN *join, table_map join_tables)
uint
idx
=
join
->
const_tables
;
double
record_count
=
1.0
;
double
read_time
=
0.0
;
for
(
JOIN_TAB
**
pos
=
join
->
best_ref
+
idx
;
(
s
=
*
pos
)
;
pos
++
)
{
/* Find the best access method from 's' to the current partial plan */
...
...
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