mirror of
https://github.com/MariaDB/server.git
synced 2025-11-25 17:25:02 +03:00
- multi_range_read_info_const now uses the new records_in_range interface - Added handler::avg_io_cost() - Don't calculate avg_io_cost() in get_sweep_read_cost if avg_io_cost is not 1.0. In this case we trust the avg_io_cost() from the handler. - Changed test_quick_select to use TIME_FOR_COMPARE instead of TIME_FOR_COMPARE_IDX to align this with the rest of the code. - Fixed bug when using test_if_cheaper_ordering where we didn't use keyread if index was changed - Fixed a bug where we didn't use index only read when using order-by-index - Added keyread_time() to HEAP. The default keyread_time() was optimized for blocks and not suitable for HEAP. The effect was the HEAP prefered table scans over ranges for btree indexes. - Fixed get_sweep_read_cost() for HEAP tables - Ensure that range and ref have same cost for simple ranges Added a small cost (MULTI_RANGE_READ_SETUP_COST) to ranges to ensure we favior ref for range for simple queries. - Fixed that matching_candidates_in_table() uses same number of records as the rest of the optimizer - Added avg_io_cost() to JT_EQ_REF cost. This helps calculate the cost for HEAP and temporary tables better. A few tests changed because of this. - heap::read_time() and heap::keyread_time() adjusted to not add +1. This was to ensure that handler::keyread_time() doesn't give higher cost for heap tables than for normal tables. One effect of this is that heap and derived tables stored in heap will prefer key access as this is now regarded as cheap. - Changed cost for index read in sql_select.cc to match multi_range_read_info_const(). All index cost calculation is now done trough one function. - 'ref' will now use quick_cost for keys if it exists. This is done so that for '=' ranges, 'ref' is prefered over 'range'. - scan_time() now takes avg_io_costs() into account - get_delayed_table_estimates() uses block_size and avg_io_cost() - Removed default argument to test_if_order_by_key(); simplifies code
314 lines
12 KiB
Plaintext
314 lines
12 KiB
Plaintext
set time_zone="+00:00";
|
|
set default_storage_engine=innodb;
|
|
create or replace table dept (
|
|
dept_id int(10) primary key,
|
|
name varchar(100)
|
|
) with system versioning;
|
|
create or replace table emp (
|
|
emp_id int(10) primary key,
|
|
dept_id int(10) not null,
|
|
name varchar(100) not null,
|
|
mgr int(10),
|
|
salary int(10) not null,
|
|
constraint `dept-emp-fk`
|
|
foreign key (dept_id) references dept (dept_id)
|
|
on delete cascade
|
|
on update restrict,
|
|
constraint `mgr-fk`
|
|
foreign key (mgr) references emp (emp_id)
|
|
on delete restrict
|
|
on update restrict
|
|
) with system versioning;
|
|
insert into dept (dept_id, name) values (10, "accounting");
|
|
insert into emp (emp_id, name, salary, dept_id, mgr) values
|
|
(1, "bill", 1000, 10, null),
|
|
(20, "john", 500, 10, 1),
|
|
(30, "jane", 750, 10,1 );
|
|
select row_start into @ts_1 from emp where name="jane";
|
|
update emp set mgr=30 where name ="john";
|
|
explain extended
|
|
with ancestors as (
|
|
select e.emp_id, e.name, e.mgr, e.salary from emp as e where name = 'bill'
|
|
union
|
|
select e.emp_id, e.name, e.mgr, e.salary from emp as e
|
|
) select * from ancestors for system_time as of @ts_1;
|
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8 100.00
|
|
2 DERIVED e ALL NULL NULL NULL NULL 4 100.00 Using where
|
|
3 UNION e ALL NULL NULL NULL NULL 4 100.00 Using where
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
|
Warnings:
|
|
Note 1003 with ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1` union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` where `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1`)/* select#1 */ select `ancestors`.`emp_id` AS `emp_id`,`ancestors`.`name` AS `name`,`ancestors`.`mgr` AS `mgr`,`ancestors`.`salary` AS `salary` from `ancestors`
|
|
select row_start into @ts_2 from emp where name="john";
|
|
explain extended /* All report to 'Bill' */
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp for system_time as of timestamp @ts_1 as e
|
|
where name = 'bill'
|
|
union
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp for system_time as of timestamp @ts_1 as e,
|
|
ancestors as a
|
|
where e.mgr = a.emp_id
|
|
)
|
|
select * from ancestors;
|
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00
|
|
2 DERIVED e ALL NULL NULL NULL NULL 4 100.00 Using where
|
|
3 RECURSIVE UNION e ALL mgr-fk NULL NULL NULL 4 100.00 Using where
|
|
3 RECURSIVE UNION <derived2> ref key0 key0 5 test.e.mgr 2 100.00
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
|
Warnings:
|
|
Note 1003 with recursive ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1` union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` join `ancestors` `a` where `a`.`emp_id` = `test`.`e`.`mgr` and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1`)/* select#1 */ select `ancestors`.`emp_id` AS `emp_id`,`ancestors`.`name` AS `name`,`ancestors`.`mgr` AS `mgr`,`ancestors`.`salary` AS `salary` from `ancestors`
|
|
/* All report to 'Bill' */
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp for system_time as of timestamp @ts_1 as e
|
|
where name = 'bill'
|
|
union
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp for system_time as of timestamp @ts_1 as e,
|
|
ancestors as a
|
|
where e.mgr = a.emp_id
|
|
)
|
|
select * from ancestors;
|
|
emp_id name mgr salary
|
|
1 bill NULL 1000
|
|
20 john 1 500
|
|
30 jane 1 750
|
|
explain extended with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e
|
|
where name = 'bill'
|
|
union
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e,
|
|
ancestors as a
|
|
where e.mgr = a.emp_id
|
|
)
|
|
select * from ancestors for system_time as of timestamp @ts_1;
|
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00
|
|
2 DERIVED e ALL NULL NULL NULL NULL 4 100.00 Using where
|
|
3 RECURSIVE UNION e ALL mgr-fk NULL NULL NULL 4 100.00 Using where
|
|
3 RECURSIVE UNION <derived2> ref key0 key0 5 test.e.mgr 2 100.00
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
|
Warnings:
|
|
Note 1003 with recursive ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1` union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` join `ancestors` `a` where `a`.`emp_id` = `test`.`e`.`mgr` and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1`)/* select#1 */ select `ancestors`.`emp_id` AS `emp_id`,`ancestors`.`name` AS `name`,`ancestors`.`mgr` AS `mgr`,`ancestors`.`salary` AS `salary` from `ancestors`
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e
|
|
where name = 'bill'
|
|
union
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e,
|
|
ancestors as a
|
|
where e.mgr = a.emp_id
|
|
)
|
|
select * from ancestors for system_time as of timestamp @ts_1;
|
|
emp_id name mgr salary
|
|
1 bill NULL 1000
|
|
20 john 1 500
|
|
30 jane 1 750
|
|
explain extended with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e
|
|
where name = 'bill'
|
|
union
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e,
|
|
ancestors as a
|
|
where e.mgr = a.emp_id
|
|
)
|
|
select name from emp where emp_id in (select emp_id from ancestors for system_time as of timestamp @ts_1);
|
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
|
1 PRIMARY emp ALL PRIMARY NULL NULL NULL 4 100.00 Using where
|
|
1 PRIMARY <derived2> ref key0 key0 5 test.emp.emp_id 2 100.00 FirstMatch(emp)
|
|
2 DERIVED e ALL NULL NULL NULL NULL 4 100.00 Using where
|
|
3 RECURSIVE UNION e ALL mgr-fk NULL NULL NULL 4 100.00 Using where
|
|
3 RECURSIVE UNION <derived2> ref key0 key0 5 test.e.mgr 2 100.00
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
|
Warnings:
|
|
Note 1003 with recursive ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1` union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` join `ancestors` `a` where `a`.`emp_id` = `test`.`e`.`mgr` and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1`)/* select#1 */ select `test`.`emp`.`name` AS `name` from `test`.`emp` FOR SYSTEM_TIME ALL semi join (`ancestors`) where `ancestors`.`emp_id` = `test`.`emp`.`emp_id` and `test`.`emp`.`row_end` = TIMESTAMP'2038-01-19 03:14:07.999999'
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e
|
|
where name = 'bill'
|
|
union
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e,
|
|
ancestors as a
|
|
where e.mgr = a.emp_id
|
|
)
|
|
select name from emp where emp_id in (select emp_id from ancestors for system_time as of timestamp @ts_1);
|
|
name
|
|
bill
|
|
john
|
|
jane
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e
|
|
where name = 'bill'
|
|
union
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e,
|
|
ancestors as a
|
|
where e.mgr = a.emp_id
|
|
)
|
|
select * from ancestors for system_time as of @ts_2,
|
|
ancestors for system_time as of @ts_2 a2;
|
|
emp_id name mgr salary emp_id name mgr salary
|
|
1 bill NULL 1000 1 bill NULL 1000
|
|
30 jane 1 750 1 bill NULL 1000
|
|
20 john 30 500 1 bill NULL 1000
|
|
1 bill NULL 1000 30 jane 1 750
|
|
30 jane 1 750 30 jane 1 750
|
|
20 john 30 500 30 jane 1 750
|
|
1 bill NULL 1000 20 john 30 500
|
|
30 jane 1 750 20 john 30 500
|
|
20 john 30 500 20 john 30 500
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e
|
|
where name = 'bill'
|
|
union
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e,
|
|
ancestors as a
|
|
where e.mgr = a.emp_id
|
|
)
|
|
select * from ancestors for system_time as of @ts_2,
|
|
ancestors for system_time as of now() a2;
|
|
ERROR HY000: Conflicting FOR SYSTEM_TIME clauses in WITH RECURSIVE
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e
|
|
where name = 'bill'
|
|
union
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e,
|
|
ancestors as a
|
|
where e.mgr = a.emp_id
|
|
)
|
|
select * from ancestors,
|
|
ancestors for system_time as of @ts_2 a2;
|
|
ERROR HY000: Conflicting FOR SYSTEM_TIME clauses in WITH RECURSIVE
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e
|
|
where name = 'bill'
|
|
union
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e,
|
|
ancestors as a
|
|
where e.mgr = a.emp_id
|
|
)
|
|
select * from ancestors for system_time as of @ts_2,
|
|
ancestors a2;
|
|
ERROR HY000: Conflicting FOR SYSTEM_TIME clauses in WITH RECURSIVE
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e
|
|
where name = 'bill'
|
|
union
|
|
select e.emp_id, e.name, e.mgr, e.salary
|
|
from emp as e,
|
|
ancestors as a
|
|
where e.mgr = a.emp_id
|
|
)
|
|
select * from ancestors for system_time as of @ts_2
|
|
where emp_id in (select * from ancestors);
|
|
ERROR HY000: Conflicting FOR SYSTEM_TIME clauses in WITH RECURSIVE
|
|
# SYSTEM_TIME to internal recursive instance is prohibited
|
|
with recursive cte as
|
|
(
|
|
select * from emp
|
|
union all
|
|
select * from cte for system_time as of @ts_1
|
|
)
|
|
select * from cte;
|
|
ERROR HY000: Table `cte` is not system-versioned
|
|
create or replace table emp ( emp_id int, name varchar(127), mgr int) with system versioning;
|
|
create or replace table addr ( emp_id int, address varchar(100)) with system versioning;
|
|
insert emp values (1, 'bill', 0), (2, 'bill', 1), (3, 'kate', 1);
|
|
insert addr values (1, 'Moscow'), (2, 'New York'), (3, 'London');
|
|
set @ts=now(6);
|
|
delete from emp;
|
|
delete from addr;
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select e.emp_id, e.name, e.mgr
|
|
from emp for system_time as of timestamp @ts as e
|
|
where name = 'bill'
|
|
union
|
|
select ee.emp_id, ee.name, ee.mgr
|
|
from emp for system_time as of timestamp @ts as ee, ancestors as a
|
|
where ee.mgr = a.emp_id
|
|
)
|
|
select * from ancestors;
|
|
emp_id name mgr
|
|
1 bill 0
|
|
2 bill 1
|
|
3 kate 1
|
|
insert emp values (4, 'john', 1);
|
|
insert addr values (4, 'Paris');
|
|
with ancestors as (select * from emp natural join addr) select * from ancestors;
|
|
emp_id name mgr address
|
|
4 john 1 Paris
|
|
with ancestors as (select * from emp natural join addr) select * from ancestors for system_time all;
|
|
emp_id name mgr address
|
|
1 bill 0 Moscow
|
|
2 bill 1 New York
|
|
3 kate 1 London
|
|
4 john 1 Paris
|
|
with ancestors as (select * from (select * from emp natural join addr) for system_time all as t) select * from ancestors;
|
|
emp_id name mgr address
|
|
1 bill 0 Moscow
|
|
2 bill 1 New York
|
|
3 kate 1 London
|
|
4 john 1 Paris
|
|
select * from (select * from emp natural join addr) for system_time all as t;
|
|
emp_id name mgr address
|
|
1 bill 0 Moscow
|
|
2 bill 1 New York
|
|
3 kate 1 London
|
|
4 john 1 Paris
|
|
drop table emp;
|
|
drop table dept;
|
|
drop table addr;
|