mirror of https://github.com/citusdata/citus.git
388 lines
15 KiB
Plaintext
388 lines
15 KiB
Plaintext
---------------------------------------------------------------------
|
|
--- materialized_view
|
|
---------------------------------------------------------------------
|
|
-- This file contains test cases for materialized view support.
|
|
-- materialized views work
|
|
-- insert into... select works with views
|
|
CREATE SCHEMA materialized_view;
|
|
SET search_path TO materialized_view, public;
|
|
CREATE VIEW air_shipped_lineitems AS SELECT * FROM lineitem_hash_part WHERE l_shipmode = 'AIR';
|
|
CREATE TABLE temp_lineitem(LIKE lineitem_hash_part);
|
|
SELECT create_distributed_table('temp_lineitem', 'l_orderkey', 'hash', 'lineitem_hash_part');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
INSERT INTO temp_lineitem SELECT * FROM air_shipped_lineitems;
|
|
SELECT count(*) FROM temp_lineitem;
|
|
count
|
|
---------------------------------------------------------------------
|
|
1706
|
|
(1 row)
|
|
|
|
-- following is a where false query, should not be inserting anything
|
|
INSERT INTO temp_lineitem SELECT * FROM air_shipped_lineitems WHERE l_shipmode = 'MAIL';
|
|
SELECT count(*) FROM temp_lineitem;
|
|
count
|
|
---------------------------------------------------------------------
|
|
1706
|
|
(1 row)
|
|
|
|
-- can create router materialized views
|
|
CREATE MATERIALIZED VIEW mode_counts_router
|
|
AS SELECT l_shipmode, count(*) FROM temp_lineitem WHERE l_orderkey = 1 GROUP BY l_shipmode;
|
|
SELECT * FROM mode_counts_router;
|
|
l_shipmode | count
|
|
---------------------------------------------------------------------
|
|
AIR | 1
|
|
(1 row)
|
|
|
|
-- can create and query materialized views
|
|
CREATE MATERIALIZED VIEW mode_counts
|
|
AS SELECT l_shipmode, count(*) FROM temp_lineitem GROUP BY l_shipmode;
|
|
SELECT * FROM mode_counts WHERE l_shipmode = 'AIR' ORDER BY 2 DESC, 1 LIMIT 10;
|
|
l_shipmode | count
|
|
---------------------------------------------------------------------
|
|
AIR | 1706
|
|
(1 row)
|
|
|
|
-- materialized views are local, cannot join with distributed tables
|
|
SELECT count(*) FROM mode_counts JOIN temp_lineitem USING (l_shipmode);
|
|
count
|
|
---------------------------------------------------------------------
|
|
1706
|
|
(1 row)
|
|
|
|
-- new data is not immediately reflected in the view
|
|
INSERT INTO temp_lineitem SELECT * FROM air_shipped_lineitems;
|
|
SELECT * FROM mode_counts WHERE l_shipmode = 'AIR' ORDER BY 2 DESC, 1 LIMIT 10;
|
|
l_shipmode | count
|
|
---------------------------------------------------------------------
|
|
AIR | 1706
|
|
(1 row)
|
|
|
|
-- refresh updates the materialised view with new data
|
|
REFRESH MATERIALIZED VIEW mode_counts;
|
|
SELECT * FROM mode_counts WHERE l_shipmode = 'AIR' ORDER BY 2 DESC, 1 LIMIT 10;
|
|
l_shipmode | count
|
|
---------------------------------------------------------------------
|
|
AIR | 3412
|
|
(1 row)
|
|
|
|
DROP MATERIALIZED VIEW mode_counts;
|
|
DROP TABLE temp_lineitem CASCADE;
|
|
NOTICE: drop cascades to materialized view mode_counts_router
|
|
-- Refresh single-shard materialized view
|
|
CREATE MATERIALIZED VIEW materialized_view AS
|
|
SELECT orders_hash_part.o_orderdate, total_price.price_sum
|
|
FROM lineitem_hash_part, orders_hash_part, (SELECT SUM(l_extendedprice) AS price_sum FROM lineitem_hash_part where l_orderkey=3) AS total_price
|
|
WHERE lineitem_hash_part.l_orderkey=orders_hash_part.o_orderkey AND lineitem_hash_part.l_orderkey=3;
|
|
REFRESH MATERIALIZED VIEW materialized_view;
|
|
SELECT count(*) FROM materialized_view;
|
|
count
|
|
---------------------------------------------------------------------
|
|
6
|
|
(1 row)
|
|
|
|
DROP MATERIALIZED VIEW materialized_view;
|
|
-- Refresh multi-shard materialized view
|
|
CREATE MATERIALIZED VIEW materialized_view AS
|
|
SELECT orders_hash_part.o_orderdate, total_price.price_sum
|
|
FROM lineitem_hash_part, orders_hash_part, (SELECT SUM(l_extendedprice) AS price_sum FROM lineitem_hash_part) AS total_price
|
|
WHERE lineitem_hash_part.l_orderkey=orders_hash_part.o_orderkey;
|
|
REFRESH MATERIALIZED VIEW materialized_view;
|
|
SELECT count(*) FROM materialized_view;
|
|
count
|
|
---------------------------------------------------------------------
|
|
12000
|
|
(1 row)
|
|
|
|
DROP MATERIALIZED VIEW materialized_view;
|
|
-- Refresh materialized view with CTE
|
|
CREATE MATERIALIZED VIEW materialized_view AS
|
|
WITH total_price AS (SELECT SUM(l_extendedprice) AS price_sum FROM lineitem_hash_part)
|
|
SELECT orders_hash_part.o_orderdate, total_price.price_sum
|
|
FROM lineitem_hash_part, orders_hash_part, total_price
|
|
WHERE lineitem_hash_part.l_orderkey=orders_hash_part.o_orderkey;
|
|
REFRESH MATERIALIZED VIEW materialized_view;
|
|
SELECT count(*) FROM materialized_view;
|
|
count
|
|
---------------------------------------------------------------------
|
|
12000
|
|
(1 row)
|
|
|
|
DROP MATERIALIZED VIEW materialized_view;
|
|
-- Refresh materialized view with join
|
|
CREATE MATERIALIZED VIEW materialized_view AS
|
|
SELECT orders_hash_part.o_orderdate, quantity_sum
|
|
FROM orders_hash_part JOIN (
|
|
SELECT l_orderkey, SUM(l_quantity) AS quantity_sum
|
|
FROM lineitem_hash_part
|
|
GROUP BY l_orderkey
|
|
) AS total_quantity
|
|
ON total_quantity.l_orderkey=orders_hash_part.o_orderkey;
|
|
REFRESH MATERIALIZED VIEW materialized_view;
|
|
SELECT count(*) FROM materialized_view;
|
|
count
|
|
---------------------------------------------------------------------
|
|
2985
|
|
(1 row)
|
|
|
|
DROP MATERIALIZED VIEW materialized_view;
|
|
-- Refresh materialized view with reference tables
|
|
CREATE MATERIALIZED VIEW materialized_view AS
|
|
SELECT orders_reference.o_orderdate, total_price.price_sum
|
|
FROM lineitem_hash_part, orders_reference, (SELECT SUM(o_totalprice) AS price_sum FROM orders_reference) AS total_price
|
|
WHERE lineitem_hash_part.l_orderkey=orders_reference.o_orderkey;
|
|
REFRESH MATERIALIZED VIEW materialized_view;
|
|
SELECT count(*) FROM materialized_view;
|
|
count
|
|
---------------------------------------------------------------------
|
|
12000
|
|
(1 row)
|
|
|
|
DROP MATERIALIZED VIEW materialized_view;
|
|
-- Refresh materialized view with table distributed after creation of view
|
|
CREATE TABLE lineitem_local_to_hash_part AS SELECT * FROM lineitem_hash_part;
|
|
CREATE TABLE orders_local_to_hash_part AS SELECT * FROM orders_hash_part;
|
|
CREATE MATERIALIZED VIEW materialized_view AS
|
|
SELECT orders_local_to_hash_part.o_orderdate, total_price.price_sum
|
|
FROM lineitem_local_to_hash_part, orders_local_to_hash_part, (SELECT SUM(l_extendedprice) AS price_sum FROM lineitem_local_to_hash_part) AS total_price
|
|
WHERE lineitem_local_to_hash_part.l_orderkey=orders_local_to_hash_part.o_orderkey;
|
|
SELECT create_distributed_table('lineitem_local_to_hash_part', 'l_orderkey');
|
|
NOTICE: Copying data from local table...
|
|
NOTICE: copying the data has completed
|
|
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
|
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$materialized_view.lineitem_local_to_hash_part$$)
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
SELECT create_distributed_table('orders_local_to_hash_part', 'o_orderkey');
|
|
NOTICE: Copying data from local table...
|
|
NOTICE: copying the data has completed
|
|
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
|
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$materialized_view.orders_local_to_hash_part$$)
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
REFRESH MATERIALIZED VIEW materialized_view;
|
|
SELECT count(*) FROM materialized_view;
|
|
count
|
|
---------------------------------------------------------------------
|
|
12000
|
|
(1 row)
|
|
|
|
DROP MATERIALIZED VIEW materialized_view;
|
|
DROP TABLE lineitem_local_to_hash_part;
|
|
DROP TABLE orders_local_to_hash_part;
|
|
-- Refresh materialized view WITH DATA
|
|
CREATE MATERIALIZED VIEW materialized_view AS
|
|
SELECT orders_hash_part.o_orderdate, total_price.price_sum
|
|
FROM lineitem_hash_part, orders_hash_part, (SELECT SUM(l_extendedprice) AS price_sum FROM lineitem_hash_part) AS total_price
|
|
WHERE lineitem_hash_part.l_orderkey=orders_hash_part.o_orderkey;
|
|
REFRESH MATERIALIZED VIEW materialized_view WITH DATA;
|
|
SELECT count(*) FROM materialized_view;
|
|
count
|
|
---------------------------------------------------------------------
|
|
12000
|
|
(1 row)
|
|
|
|
DROP MATERIALIZED VIEW materialized_view;
|
|
-- Refresh materialized view WITH NO DATA
|
|
CREATE MATERIALIZED VIEW materialized_view AS
|
|
SELECT orders_hash_part.o_orderdate, total_price.price_sum
|
|
FROM lineitem_hash_part, orders_hash_part, (SELECT SUM(l_extendedprice) AS price_sum FROM lineitem_hash_part) AS total_price
|
|
WHERE lineitem_hash_part.l_orderkey=orders_hash_part.o_orderkey;
|
|
REFRESH MATERIALIZED VIEW materialized_view WITH NO DATA;
|
|
SELECT count(*) FROM materialized_view;
|
|
ERROR: materialized view "materialized_view" has not been populated
|
|
HINT: Use the REFRESH MATERIALIZED VIEW command.
|
|
DROP MATERIALIZED VIEW materialized_view;
|
|
-- Refresh materialized view CONCURRENTLY
|
|
CREATE MATERIALIZED VIEW materialized_view AS
|
|
SELECT orders_hash_part.o_orderdate, SUM(total_price.price_sum)
|
|
FROM lineitem_hash_part, orders_hash_part, (SELECT SUM(l_extendedprice) AS price_sum FROM lineitem_hash_part) AS total_price
|
|
WHERE lineitem_hash_part.l_orderkey=orders_hash_part.o_orderkey
|
|
GROUP BY orders_hash_part.o_orderdate;
|
|
CREATE UNIQUE INDEX materialized_view_index ON materialized_view (o_orderdate);
|
|
REFRESH MATERIALIZED VIEW CONCURRENTLY materialized_view;
|
|
SELECT count(*) FROM materialized_view;
|
|
count
|
|
---------------------------------------------------------------------
|
|
1699
|
|
(1 row)
|
|
|
|
DROP MATERIALIZED VIEW materialized_view;
|
|
DROP SCHEMA materialized_view CASCADE;
|
|
NOTICE: drop cascades to view air_shipped_lineitems
|
|
-- modify statements on/with views
|
|
-- create two tables and a view
|
|
CREATE TABLE large (id int, tenant_id int);
|
|
CREATE TABLE small (id int, tenant_id int);
|
|
SELECT create_distributed_table('large','tenant_id');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
SELECT create_distributed_table('small','tenant_id');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
\copy small FROM STDIN DELIMITER ','
|
|
CREATE MATERIALIZED VIEW small_view AS SELECT * from small where id < 100;
|
|
\copy large FROM STDIN DELIMITER ','
|
|
-- running any kind of modify statements "on" materialized views is not supported by postgres
|
|
UPDATE small_view SET id = 1;
|
|
ERROR: cannot change materialized view "small_view"
|
|
-- for now, using materialized views in modify statements' FROM / WHERE clauses is not supported
|
|
UPDATE large SET id=20 FROM small_view WHERE small_view.id=large.id;
|
|
SELECT * FROM large ORDER BY 1, 2;
|
|
id | tenant_id
|
|
---------------------------------------------------------------------
|
|
2 | 3
|
|
5 | 4
|
|
20 | 2
|
|
20 | 5
|
|
(4 rows)
|
|
|
|
-- test on a router executable update statement, this will also fail
|
|
UPDATE large SET id=28 FROM small_view WHERE small_view.id=large.id and small_view.tenant_id=2 and large.tenant_id=2;
|
|
SELECT * FROM large ORDER BY 1, 2;
|
|
id | tenant_id
|
|
---------------------------------------------------------------------
|
|
2 | 3
|
|
5 | 4
|
|
20 | 2
|
|
20 | 5
|
|
(4 rows)
|
|
|
|
-- delete statement on large with subquery, this should succeed
|
|
DELETE FROM large WHERE tenant_id in (SELECT tenant_id FROM small_view);
|
|
SELECT * FROM large ORDER BY 1, 2;
|
|
id | tenant_id
|
|
---------------------------------------------------------------------
|
|
20 | 5
|
|
(1 row)
|
|
|
|
-- INSERT INTO views is already not supported by PostgreSQL
|
|
INSERT INTO small_view VALUES(3, 3);
|
|
ERROR: cannot change materialized view "small_view"
|
|
DROP TABLE small CASCADE;
|
|
NOTICE: drop cascades to materialized view small_view
|
|
DROP TABLE large;
|
|
-- now, run the same modify statement tests on a partitioned table
|
|
CREATE TABLE small (id int, tenant_id int);
|
|
CREATE TABLE large_partitioned (id int, tenant_id int) partition by range(tenant_id);
|
|
CREATE TABLE large_partitioned_p1 PARTITION OF large_partitioned FOR VALUES FROM (1) TO (10);
|
|
CREATE TABLE large_partitioned_p2 PARTITION OF large_partitioned FOR VALUES FROM (10) TO (20);
|
|
CREATE TABLE large_partitioned_p3 PARTITION OF large_partitioned FOR VALUES FROM (20) TO (100);
|
|
SELECT create_distributed_table('large_partitioned','tenant_id');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
SELECT create_distributed_table('small','tenant_id');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
\copy small FROM STDIN DELIMITER ','
|
|
CREATE MATERIALIZED VIEW small_view AS SELECT * from small where id < 100;
|
|
\copy large_partitioned FROM STDIN DELIMITER ','
|
|
-- running modify statements "on" views is still not supported, hence below two statements will fail
|
|
UPDATE small_view SET id = 1;
|
|
ERROR: cannot change materialized view "small_view"
|
|
DELETE FROM small_view;
|
|
ERROR: cannot change materialized view "small_view"
|
|
-- using mat. view in modify statements' FROM / WHERE clauses is not valid yet
|
|
UPDATE large_partitioned SET id=20 FROM small_view WHERE small_view.id=large_partitioned.id;
|
|
SELECT * FROM large_partitioned ORDER BY 1, 2;
|
|
id | tenant_id
|
|
---------------------------------------------------------------------
|
|
2 | 3
|
|
5 | 4
|
|
20 | 2
|
|
20 | 5
|
|
26 | 32
|
|
29 | 15
|
|
60 | 51
|
|
(7 rows)
|
|
|
|
-- delete statement on large_partitioned
|
|
DELETE FROM large_partitioned WHERE id in (SELECT id FROM small_view);
|
|
SELECT * FROM large_partitioned ORDER BY 1, 2;
|
|
id | tenant_id
|
|
---------------------------------------------------------------------
|
|
2 | 3
|
|
5 | 4
|
|
20 | 2
|
|
20 | 5
|
|
26 | 32
|
|
29 | 15
|
|
60 | 51
|
|
(7 rows)
|
|
|
|
-- we should still have identical rows for next test statement, then insert new rows to both tables
|
|
INSERT INTO large_partitioned VALUES(14, 14);
|
|
INSERT INTO small VALUES(14, 14);
|
|
-- delete statement with CTE
|
|
WITH all_small_view_ids AS (SELECT id FROM small_view)
|
|
DELETE FROM large_partitioned WHERE id in (SELECT * FROM all_small_view_ids);
|
|
-- make sure that materialized view in a CTE/subquery can be joined with a distributed table
|
|
WITH cte AS (SELECT *, random() FROM small_view) SELECT count(*) FROM cte JOIN small USING(id);
|
|
count
|
|
---------------------------------------------------------------------
|
|
4
|
|
(1 row)
|
|
|
|
SELECT count(*) FROM (SELECT *, random() FROM small_view) as subquery JOIN small USING(id);
|
|
count
|
|
---------------------------------------------------------------------
|
|
4
|
|
(1 row)
|
|
|
|
CREATE MATERIALIZED VIEW only_intermedate_result AS
|
|
WITH cte_1 AS (SELECT * FROM small OFFSET 0) SELECT * FROM cte_1 ORDER BY 1,2;
|
|
SELECT * FROM only_intermedate_result ORDER BY 1,2;
|
|
id | tenant_id
|
|
---------------------------------------------------------------------
|
|
1 | 2
|
|
6 | 3
|
|
7 | 4
|
|
8 | 2
|
|
14 | 14
|
|
250 | 25
|
|
470 | 13
|
|
(7 rows)
|
|
|
|
INSERT INTO small VALUES (1000000,1000000);
|
|
REFRESH MATERIALIZED VIEW only_intermedate_result;
|
|
SELECT * FROM only_intermedate_result ORDER BY 1,2;
|
|
id | tenant_id
|
|
---------------------------------------------------------------------
|
|
1 | 2
|
|
6 | 3
|
|
7 | 4
|
|
8 | 2
|
|
14 | 14
|
|
250 | 25
|
|
470 | 13
|
|
1000000 | 1000000
|
|
(8 rows)
|
|
|
|
DROP TABLE large_partitioned;
|
|
DROP TABLE small CASCADE;
|
|
NOTICE: drop cascades to 2 other objects
|
|
DETAIL: drop cascades to materialized view small_view
|
|
drop cascades to materialized view only_intermedate_result
|