Skip to content

Commit

Permalink
opt: add Index.PartitionByListPrefixes to catalog
Browse files Browse the repository at this point in the history
Add a catalog function that returns index regions of interest based on
PARTITION BY LIST values. This information will be used for an "index
skip scan".

Informs cockroachdb#38031.

Release note: None
  • Loading branch information
RaduBerinde committed Jul 13, 2019
1 parent a466599 commit 39c2ec8
Show file tree
Hide file tree
Showing 8 changed files with 402 additions and 16 deletions.
169 changes: 168 additions & 1 deletion pkg/ccl/logictestccl/testdata/logic_test/partitioning
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# LogicTest: local
# LogicTest: local-opt

statement error syntax
CREATE TABLE t (a INT, b INT, c INT, PRIMARY KEY (a, b)) PARTITION BY LIST ()
Expand Down Expand Up @@ -399,6 +399,21 @@ ok1 CREATE TABLE ok1 (
PARTITION p2 VALUES IN ((2))
)

query T
EXPLAIN (OPT, CATALOG) SELECT * from ok1
----
TABLE ok1
├── a int not null
├── b int not null
├── c int
└── INDEX primary
├── a int not null
├── b int not null
└── partition by list prefixes
├── (1)
└── (2)
scan ok1

statement ok
CREATE TABLE ok2 (a INT, b INT, c INT, PRIMARY KEY (a, b)) PARTITION BY LIST (a) (
PARTITION p1 VALUES IN ((1)),
Expand All @@ -419,6 +434,21 @@ ok2 CREATE TABLE ok2 (
PARTITION p2 VALUES IN ((2))
)

query T
EXPLAIN (OPT, CATALOG) SELECT * from ok2
----
TABLE ok2
├── a int not null
├── b int not null
├── c int
└── INDEX primary
├── a int not null
├── b int not null
└── partition by list prefixes
├── (1)
└── (2)
scan ok2

statement ok
CREATE TABLE ok3 (a INT, b INT, c INT, PRIMARY KEY (a, b)) PARTITION BY LIST (a) (
PARTITION p1 VALUES IN (1),
Expand All @@ -439,6 +469,20 @@ ok3 CREATE TABLE ok3 (
PARTITION p2 VALUES IN ((DEFAULT))
)

query T
EXPLAIN (OPT, CATALOG) SELECT * from ok3
----
TABLE ok3
├── a int not null
├── b int not null
├── c int
└── INDEX primary
├── a int not null
├── b int not null
└── partition by list prefixes
└── (1)
scan ok3

statement ok
CREATE TABLE ok4 (a INT, b INT, c INT, PRIMARY KEY (a, b)) PARTITION BY LIST (a, b) (
PARTITION p1 VALUES IN ((1, 1)),
Expand All @@ -463,6 +507,22 @@ ok4 CREATE TABLE ok4 (
PARTITION p4 VALUES IN ((DEFAULT, DEFAULT))
)

query T
EXPLAIN (OPT, CATALOG) SELECT * from ok4
----
TABLE ok4
├── a int not null
├── b int not null
├── c int
└── INDEX primary
├── a int not null
├── b int not null
└── partition by list prefixes
├── (1, 1)
├── (1)
└── (2, 3)
scan ok4

statement ok
CREATE TABLE ok5 (a INT, b INT, c INT, PRIMARY KEY (a, b)) PARTITION BY LIST (a) (
PARTITION p1 VALUES IN (1) PARTITION BY LIST (b) (
Expand All @@ -475,6 +535,21 @@ CREATE TABLE ok5 (a INT, b INT, c INT, PRIMARY KEY (a, b)) PARTITION BY LIST (a)
PARTITION p3 VALUES IN (DEFAULT)
)

query T
EXPLAIN (OPT, CATALOG) SELECT * from ok5
----
TABLE ok5
├── a int not null
├── b int not null
├── c int
└── INDEX primary
├── a int not null
├── b int not null
└── partition by list prefixes
├── (1)
└── (2)
scan ok5

query TT
SHOW CREATE TABLE ok5
----
Expand Down Expand Up @@ -515,6 +590,18 @@ ok6 CREATE TABLE ok6 (
PARTITION p2 VALUES FROM (1) TO (2)
)

query T
EXPLAIN (OPT, CATALOG) SELECT * from ok6
----
TABLE ok6
├── a int not null
├── b int not null
├── c int
└── INDEX primary
├── a int not null
└── b int not null
scan ok6

statement ok
CREATE TABLE ok7 (a INT, b INT, c INT, PRIMARY KEY (a, b)) PARTITION BY RANGE (a) (
PARTITION p1 VALUES FROM ((0)) TO (((1)))
Expand All @@ -533,6 +620,18 @@ ok7 CREATE TABLE ok7 (
PARTITION p1 VALUES FROM (0) TO (1)
)

query T
EXPLAIN (OPT, CATALOG) SELECT * from ok7
----
TABLE ok7
├── a int not null
├── b int not null
├── c int
└── INDEX primary
├── a int not null
└── b int not null
scan ok7

statement ok
CREATE TABLE ok8 (a INT, b INT, c INT, PRIMARY KEY (a, b)) PARTITION BY RANGE (a) (
PARTITION p1 VALUES FROM (MINVALUE) TO (1),
Expand All @@ -555,6 +654,18 @@ ok8 CREATE TABLE ok8 (
PARTITION p3 VALUES FROM (2) TO (MAXVALUE)
)

query T
EXPLAIN (OPT, CATALOG) SELECT * from ok8
----
TABLE ok8
├── a int not null
├── b int not null
├── c int
└── INDEX primary
├── a int not null
└── b int not null
scan ok8

statement ok
CREATE TABLE ok9 (a INT, b INT, c INT, PRIMARY KEY (a, b)) PARTITION BY RANGE (a, b) (
PARTITION p1 VALUES FROM (MINVALUE, MINVALUE) TO (1, MAXVALUE),
Expand All @@ -579,6 +690,18 @@ ok9 CREATE TABLE ok9 (
PARTITION p4 VALUES FROM (3, MAXVALUE) TO (MAXVALUE, MAXVALUE)
)

query T
EXPLAIN (OPT, CATALOG) SELECT * from ok9
----
TABLE ok9
├── a int not null
├── b int not null
├── c int
└── INDEX primary
├── a int not null
└── b int not null
scan ok9

statement ok
CREATE TABLE ok10 (a INT, b INT, c INT, PRIMARY KEY (a, b)) PARTITION BY RANGE (a, b) (
PARTITION p1 VALUES FROM (MINVALUE, MINVALUE) TO (1, 1),
Expand All @@ -605,6 +728,18 @@ ok10 CREATE TABLE ok10 (
PARTITION p5 VALUES FROM (3, 4) TO (MAXVALUE, MAXVALUE)
)

query T
EXPLAIN (OPT, CATALOG) SELECT * from ok10
----
TABLE ok10
├── a int not null
├── b int not null
├── c int
└── INDEX primary
├── a int not null
└── b int not null
scan ok10

statement ok
CREATE TABLE ok11 (a INT, b INT, c INT, PRIMARY KEY (a, b, c)) PARTITION BY LIST (a) (
PARTITION p1 VALUES IN (1) PARTITION BY LIST (b) (
Expand Down Expand Up @@ -639,6 +774,22 @@ ok11 CREATE TABLE ok11 (
)
)

query T
EXPLAIN (OPT, CATALOG) SELECT * from ok11
----
TABLE ok11
├── a int not null
├── b int not null
├── c int not null
└── INDEX primary
├── a int not null
├── b int not null
├── c int not null
└── partition by list prefixes
├── (1)
└── (6)
scan ok11

statement ok
CREATE TABLE IF NOT EXISTS ok12 (a INT, b INT, c INT, PRIMARY KEY (a, b)) PARTITION BY LIST (a) (
PARTITION pu VALUES IN (NULL),
Expand All @@ -662,6 +813,22 @@ ok12 CREATE TABLE ok12 (
PARTITION p2 VALUES IN ((2))
)

query T
EXPLAIN (OPT, CATALOG) SELECT * from ok12
----
TABLE ok12
├── a int not null
├── b int not null
├── c int
└── INDEX primary
├── a int not null
├── b int not null
└── partition by list prefixes
├── (NULL)
├── (1)
└── (2)
scan ok12

# Verify that creating a partition that includes NULL does not change the
# implicit NOT NULL contrainst of a primary key.
statement error null value in column "a" violates not-null constraint
Expand Down
34 changes: 34 additions & 0 deletions pkg/sql/opt/cat/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,40 @@ type Index interface {

// Span returns the KV span associated with the index.
Span() roachpb.Span

// PartitionByListPrefixes returns values that correspond to PARTITION BY LIST
// values. Specifically, it returns a list of tuples where each tuple contains
// values for a prefix of index columns (indicating a region of the index).
// Each tuple corresponds to a configured partition or subpartition.
//
// Note: this function decodes and allocates datums; use sparingly.
//
// Example:
//
// CREATE INDEX idx ON t(region,subregion,val) PARTITION BY LIST (region,subregion) (
// PARTITION westcoast VALUES IN (('us', 'seattle'), ('us', 'cali')),
// PARTITION us VALUES IN (('us', DEFAULT)),
// PARTITION eu VALUES IN (('eu', DEFAULT)),
// PARTITION default VALUES IN (DEFAULT)
// );
//
// PartitionByListPrefixes() returns
// ('us', 'seattle'),
// ('us', 'cali'),
// ('us'),
// ('eu').
//
// The intended use of this function is for index skip scans. Each tuple
// corresponds to a region of the index that we can constrain further. In the
// example above: if we have a val=1 filter, instead of a full index scan we
// can skip most of the data under /us/cali and /us/seattle by scanning spans:
// [ - /us/cali )
// [ /us/cali/1 - /us/cali/1 ]
// [ /us/cali\x00 - /us/seattle )
// [ /us/seattle/1 - /us/seattle/1 ]
// [ /us/seattle\x00 - ]
//
PartitionByListPrefixes() []tree.Datums
}

// IndexColumn describes a single column that is part of an index definition.
Expand Down
11 changes: 11 additions & 0 deletions pkg/sql/opt/cat/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ func FindTableColumnByName(tab Table, name tree.Name) int {
// and testing.
func FormatTable(cat Catalog, tab Table, tp treeprinter.Node) {
child := tp.Childf("TABLE %s", tab.Name().TableName)
if tab.IsVirtualTable() {
child.Child("virtual table")
}

var buf bytes.Buffer
for i := 0; i < tab.DeletableColumnCount(); i++ {
Expand Down Expand Up @@ -207,6 +210,14 @@ func formatCatalogIndex(tab Table, ord int, tp treeprinter.Node) {
}

FormatZone(idx.Zone(), child)

partPrefixes := idx.PartitionByListPrefixes()
if len(partPrefixes) != 0 {
c := child.Child("partition by list prefixes")
for i := range partPrefixes {
c.Child(partPrefixes[i].String())
}
}
}

// formatColPrefix returns a string representation of a list of columns. The
Expand Down
17 changes: 12 additions & 5 deletions pkg/sql/opt/testutils/testcat/create_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ func (tc *Catalog) CreateTable(stmt *tree.CreateTable) *Table {
} else if !tab.IsVirtual {
tab.addPrimaryColumnIndex("rowid")
}
if stmt.PartitionBy != nil {
if len(tab.Indexes) == 0 {
panic("cannot partition virtual table")
}
tab.Indexes[0].partitionBy = stmt.PartitionBy
}

// Add check constraints.
for _, def := range stmt.Defs {
Expand Down Expand Up @@ -368,11 +374,12 @@ func (tt *Table) addColumn(def *tree.ColumnTableDef) {

func (tt *Table) addIndex(def *tree.IndexTableDef, typ indexType) *Index {
idx := &Index{
IdxName: tt.makeIndexName(def.Name, typ),
Unique: typ != nonUniqueIndex,
Inverted: def.Inverted,
IdxZone: &config.ZoneConfig{},
table: tt,
IdxName: tt.makeIndexName(def.Name, typ),
Unique: typ != nonUniqueIndex,
Inverted: def.Inverted,
IdxZone: &config.ZoneConfig{},
table: tt,
partitionBy: def.PartitionBy,
}

// Look for name suffixes indicating this is a mutation index.
Expand Down
Loading

0 comments on commit 39c2ec8

Please sign in to comment.