mirror of
https://github.com/HypoPG/hypopg
synced 2026-05-24 01:28:51 +00:00
Add support for hypothetical index on partitioned tables.
This commit is contained in:
parent
098c8069f1
commit
205482a733
7 changed files with 204 additions and 5 deletions
8
Makefile
8
Makefile
|
|
@ -39,6 +39,14 @@ ifneq ($(MAJORVERSION),$(filter $(MAJORVERSION), 9.2 9.3 9.4))
|
|||
REGRESS += hypo_brin
|
||||
endif
|
||||
|
||||
ifeq ($(MAJORVERSION),10)
|
||||
REGRESS += hypo_index_part_10
|
||||
endif
|
||||
|
||||
ifneq ($(MAJORVERSION),$(filter $(MAJORVERSION), 9.2 9.3 9.4 9.5 9.6 10))
|
||||
REGRESS += hypo_index_part
|
||||
endif
|
||||
|
||||
DEBUILD_ROOT = /tmp/$(EXTENSION)
|
||||
|
||||
deb: release-zip
|
||||
|
|
|
|||
65
expected/hypo_index_part.out
Normal file
65
expected/hypo_index_part.out
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
-- Hypothetical on partitioned tabled
|
||||
CREATE TABLE hypo_part(id1 integer, id2 integer, id3 integer)
|
||||
PARTITION BY LIST (id1);
|
||||
CREATE TABLE hypo_part_1
|
||||
PARTITION OF hypo_part FOR VALUES IN (1)
|
||||
PARTITION BY LIST (id2);
|
||||
CREATE TABLE hypo_part_1_1
|
||||
PARTITION OF hypo_part_1 FOR VALUES IN (1);
|
||||
INSERT INTO hypo_part SELECT 1, 1, generate_series(1, 10000);
|
||||
ANALYZE hypo_part;
|
||||
SET enable_seqscan = 0;
|
||||
-- hypothetical index on root partitioned table should work
|
||||
SELECT COUNT(*) AS nb FROM hypopg_create_index('CREATE INDEX ON hypo_part (id3)');
|
||||
nb
|
||||
----
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT 1, COUNT(*) FROM do_explain('SELECT * FROM hypo_part WHERE id3 = 1') e
|
||||
WHERE e ~ 'Index.*<\d+>btree_hypo_part.*';
|
||||
?column? | count
|
||||
----------+-------
|
||||
1 | 1
|
||||
(1 row)
|
||||
|
||||
SELECT hypopg_reset();
|
||||
hypopg_reset
|
||||
--------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- hypothetical index on non-root partitioned table should work
|
||||
SELECT COUNT(*) AS nb FROM hypopg_create_index('CREATE INDEX ON hypo_part_1 (id3)');
|
||||
nb
|
||||
----
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT 2, COUNT(*) FROM do_explain('SELECT * FROM hypo_part_1 WHERE id3 = 1') e
|
||||
WHERE e ~ 'Index.*<\d+>btree_hypo_part.*';
|
||||
?column? | count
|
||||
----------+-------
|
||||
2 | 1
|
||||
(1 row)
|
||||
|
||||
SELECT hypopg_reset();
|
||||
hypopg_reset
|
||||
--------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- hypothetical index on partition should work
|
||||
SELECT COUNT(*) AS nb FROM hypopg_create_index('CREATE INDEX ON hypo_part_1_1 (id3)');
|
||||
nb
|
||||
----
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT 3, COUNT(*) FROM do_explain('SELECT * FROM hypo_part_1_1 WHERE id3 = 1') e
|
||||
WHERE e ~ 'Index.*<\d+>btree_hypo_part.*';
|
||||
?column? | count
|
||||
----------+-------
|
||||
3 | 1
|
||||
(1 row)
|
||||
|
||||
32
expected/hypo_index_part_10.out
Normal file
32
expected/hypo_index_part_10.out
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
-- Hypothetical on partitioned tabled
|
||||
CREATE TABLE hypo_part(id1 integer, id2 integer, id3 integer)
|
||||
PARTITION BY LIST (id1);
|
||||
CREATE TABLE hypo_part_1
|
||||
PARTITION OF hypo_part FOR VALUES IN (1)
|
||||
PARTITION BY LIST (id2);
|
||||
CREATE TABLE hypo_part_1_1
|
||||
PARTITION OF hypo_part_1 FOR VALUES IN (1);
|
||||
INSERT INTO hypo_part SELECT 1, 1, generate_series(1, 10000);
|
||||
ANALYZE hypo_part;
|
||||
-- hypothetical index on root partitioned table should not work
|
||||
SELECT hypopg_create_index('CREATE INDEX ON hypo_part (id1)');
|
||||
ERROR: hypopg: cannot create hypothetical index on partitioned table "hypo_part"
|
||||
-- hypothetical index on non-root partitioned table should not work
|
||||
SELECT hypopg_create_index('CREATE INDEX ON hypo_part_1 (id1)');
|
||||
ERROR: hypopg: cannot create hypothetical index on partitioned table "hypo_part_1"
|
||||
-- hypothetical index on partition should work
|
||||
SELECT COUNT(*) AS nb FROM hypopg_create_index('CREATE INDEX ON hypo_part_1_1 (id3)');
|
||||
nb
|
||||
----
|
||||
1
|
||||
(1 row)
|
||||
|
||||
-- Should use hypothetical index
|
||||
SET enable_seqscan = 0;
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo_part WHERE id3 = 1') e
|
||||
WHERE e ~ 'Index.*<\d+>btree_hypo_part_1_1.*';
|
||||
count
|
||||
-------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
39
hypopg.c
39
hypopg.c
|
|
@ -17,6 +17,12 @@
|
|||
#include "postgres.h"
|
||||
#include "fmgr.h"
|
||||
|
||||
#if PG_VERSION_NUM >= 110000
|
||||
#include "catalog/partition.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#endif
|
||||
|
||||
#include "include/hypopg.h"
|
||||
#include "include/hypopg_import.h"
|
||||
#include "include/hypopg_index.h"
|
||||
|
|
@ -75,6 +81,7 @@ static void hypo_get_relation_info_hook(PlannerInfo *root,
|
|||
RelOptInfo *rel);
|
||||
static get_relation_info_hook_type prev_get_relation_info_hook = NULL;
|
||||
|
||||
static bool hypo_index_match_table(hypoIndex *entry, Oid relid);
|
||||
static bool hypo_query_walker(Node *node);
|
||||
|
||||
void
|
||||
|
|
@ -256,6 +263,35 @@ hypo_utility_hook(
|
|||
|
||||
}
|
||||
|
||||
static bool
|
||||
hypo_index_match_table(hypoIndex *entry, Oid relid)
|
||||
{
|
||||
/* Hypothetical index on the exact same relation, use it. */
|
||||
if (entry->relid == relid)
|
||||
return true;
|
||||
#if PG_VERSION_NUM >= 110000
|
||||
/*
|
||||
* If the table is a partition, see if the hypothetical index belongs to
|
||||
* one of the partition parent.
|
||||
*/
|
||||
if (get_rel_relispartition(relid))
|
||||
{
|
||||
List *parents = get_partition_ancestors(relid);
|
||||
ListCell *lc;
|
||||
|
||||
foreach(lc, parents)
|
||||
{
|
||||
Oid oid = lfirst_oid(lc);
|
||||
|
||||
if (oid == entry->relid)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Detect if the current utility command is compatible with hypothetical indexes
|
||||
* i.e. an EXPLAIN, no ANALYZE
|
||||
*/
|
||||
|
|
@ -292,6 +328,7 @@ hypo_query_walker(Node *parsetree)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Reset the isExplain flag after each query */
|
||||
static void
|
||||
hypo_executorEnd_hook(QueryDesc *queryDesc)
|
||||
|
|
@ -333,7 +370,7 @@ hypo_get_relation_info_hook(PlannerInfo *root,
|
|||
{
|
||||
hypoIndex *entry = (hypoIndex *) lfirst(lc);
|
||||
|
||||
if (entry->relid == relationObjectId)
|
||||
if (hypo_index_match_table(entry, RelationGetRelid(relation)))
|
||||
{
|
||||
/*
|
||||
* hypothetical index found, add it to the relation's
|
||||
|
|
|
|||
|
|
@ -366,18 +366,19 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
{
|
||||
#if PG_VERSION_NUM >= 90300
|
||||
case RELKIND_MATVIEW:
|
||||
#endif
|
||||
#if PG_VERSION_NUM >= 110000
|
||||
case RELKIND_PARTITIONED_TABLE:
|
||||
#endif
|
||||
case RELKIND_RELATION:
|
||||
/* this is supported */
|
||||
break;
|
||||
#if PG_VERSION_NUM >= 100000
|
||||
#if PG_VERSION_NUM < 110000
|
||||
#if PG_VERSION_NUM >= 100000 && PG_VERSION_NUM < 110000
|
||||
case RELKIND_PARTITIONED_TABLE:
|
||||
elog(ERROR, "hypopg: cannot create hypothetical index on"
|
||||
" partitioned table \"%s\"", node->relation->relname);
|
||||
#endif /* pg11- */
|
||||
break;
|
||||
#endif /* pg10- */
|
||||
#endif
|
||||
default:
|
||||
elog(ERROR, "hypopg: \"%s\" is not a table"
|
||||
#if PG_VERSION_NUM >= 90300
|
||||
|
|
|
|||
30
test/sql/hypo_index_part.sql
Normal file
30
test/sql/hypo_index_part.sql
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
-- Hypothetical on partitioned tabled
|
||||
|
||||
CREATE TABLE hypo_part(id1 integer, id2 integer, id3 integer)
|
||||
PARTITION BY LIST (id1);
|
||||
CREATE TABLE hypo_part_1
|
||||
PARTITION OF hypo_part FOR VALUES IN (1)
|
||||
PARTITION BY LIST (id2);
|
||||
CREATE TABLE hypo_part_1_1
|
||||
PARTITION OF hypo_part_1 FOR VALUES IN (1);
|
||||
|
||||
INSERT INTO hypo_part SELECT 1, 1, generate_series(1, 10000);
|
||||
ANALYZE hypo_part;
|
||||
SET enable_seqscan = 0;
|
||||
|
||||
-- hypothetical index on root partitioned table should work
|
||||
SELECT COUNT(*) AS nb FROM hypopg_create_index('CREATE INDEX ON hypo_part (id3)');
|
||||
SELECT 1, COUNT(*) FROM do_explain('SELECT * FROM hypo_part WHERE id3 = 1') e
|
||||
WHERE e ~ 'Index.*<\d+>btree_hypo_part.*';
|
||||
SELECT hypopg_reset();
|
||||
|
||||
-- hypothetical index on non-root partitioned table should work
|
||||
SELECT COUNT(*) AS nb FROM hypopg_create_index('CREATE INDEX ON hypo_part_1 (id3)');
|
||||
SELECT 2, COUNT(*) FROM do_explain('SELECT * FROM hypo_part_1 WHERE id3 = 1') e
|
||||
WHERE e ~ 'Index.*<\d+>btree_hypo_part.*';
|
||||
SELECT hypopg_reset();
|
||||
|
||||
-- hypothetical index on partition should work
|
||||
SELECT COUNT(*) AS nb FROM hypopg_create_index('CREATE INDEX ON hypo_part_1_1 (id3)');
|
||||
SELECT 3, COUNT(*) FROM do_explain('SELECT * FROM hypo_part_1_1 WHERE id3 = 1') e
|
||||
WHERE e ~ 'Index.*<\d+>btree_hypo_part.*';
|
||||
26
test/sql/hypo_index_part_10.sql
Normal file
26
test/sql/hypo_index_part_10.sql
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
-- Hypothetical on partitioned tabled
|
||||
|
||||
CREATE TABLE hypo_part(id1 integer, id2 integer, id3 integer)
|
||||
PARTITION BY LIST (id1);
|
||||
CREATE TABLE hypo_part_1
|
||||
PARTITION OF hypo_part FOR VALUES IN (1)
|
||||
PARTITION BY LIST (id2);
|
||||
CREATE TABLE hypo_part_1_1
|
||||
PARTITION OF hypo_part_1 FOR VALUES IN (1);
|
||||
|
||||
INSERT INTO hypo_part SELECT 1, 1, generate_series(1, 10000);
|
||||
ANALYZE hypo_part;
|
||||
|
||||
-- hypothetical index on root partitioned table should not work
|
||||
SELECT hypopg_create_index('CREATE INDEX ON hypo_part (id1)');
|
||||
|
||||
-- hypothetical index on non-root partitioned table should not work
|
||||
SELECT hypopg_create_index('CREATE INDEX ON hypo_part_1 (id1)');
|
||||
|
||||
-- hypothetical index on partition should work
|
||||
SELECT COUNT(*) AS nb FROM hypopg_create_index('CREATE INDEX ON hypo_part_1_1 (id3)');
|
||||
|
||||
-- Should use hypothetical index
|
||||
SET enable_seqscan = 0;
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo_part WHERE id3 = 1') e
|
||||
WHERE e ~ 'Index.*<\d+>btree_hypo_part_1_1.*';
|
||||
Loading…
Reference in a new issue