github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/cat/index.go (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package cat 12 13 import ( 14 "github.com/cockroachdb/cockroach/pkg/roachpb" 15 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 16 ) 17 18 // IndexOrdinal identifies an index (in the context of a Table). 19 type IndexOrdinal = int 20 21 // PrimaryIndex selects the primary index of a table when calling the 22 // Table.Index method. Every table is guaranteed to have a unique primary 23 // index, even if it meant adding a hidden unique rowid column. 24 const PrimaryIndex IndexOrdinal = 0 25 26 // Index is an interface to a database index, exposing only the information 27 // needed by the query optimizer. Every index is treated as unique by the 28 // optimizer. If an index was declared as non-unique, then the system will add 29 // implicit columns from the primary key in order to make it unique (and even 30 // add an implicit primary key based on a hidden rowid column if a primary key 31 // was not explicitly declared). 32 type Index interface { 33 // ID is the stable identifier for this index that is guaranteed to be 34 // unique within the owning table. See the comment for StableID for more 35 // detail. 36 ID() StableID 37 38 // Name is the name of the index. 39 Name() tree.Name 40 41 // Table returns a reference to the table this index is based on. 42 Table() Table 43 44 // Ordinal returns the ordinal of this index within the context of its Table. 45 // Specifically idx = Table().Index(idx.Ordinal). 46 Ordinal() int 47 48 // IsUnique returns true if this index is declared as UNIQUE in the schema. 49 IsUnique() bool 50 51 // IsInverted returns true if this is an inverted index. 52 IsInverted() bool 53 54 // ColumnCount returns the number of columns in the index. This includes 55 // columns that were part of the index definition (including the STORING 56 // clause), as well as implicitly added primary key columns. 57 ColumnCount() int 58 59 // Predicate returns the partial index predicate expression and true if the 60 // index is a partial index. If it is not a partial index, the empty string 61 // and false are returned. 62 Predicate() (string, bool) 63 64 // KeyColumnCount returns the number of columns in the index that are part 65 // of its unique key. No two rows in the index will have the same values for 66 // those columns (where NULL values are treated as equal). Every index has a 67 // set of key columns, regardless of how it was defined, because Cockroach 68 // will implicitly add primary key columns to any index which would not 69 // otherwise have a key, like when: 70 // 71 // 1. Index was not declared as UNIQUE. 72 // 2. Index was UNIQUE, but one or more columns have NULL values. 73 // 74 // The second case is subtle, because UNIQUE indexes treat NULL values as if 75 // they are *not* equal to one another. For example, this is allowed with a 76 // unique (b, c) index, even though it appears there are duplicate rows: 77 // 78 // b c 79 // ------- 80 // NULL 1 81 // NULL 1 82 // 83 // Since keys treat NULL values as if they *are* equal to each other, 84 // Cockroach must append the primary key columns in order to ensure this 85 // index has a key. If the primary key of this table was column (a), then 86 // the key of this secondary index would be (b,c,a). 87 // 88 // The key columns are always a prefix of the full column list, where 89 // KeyColumnCount <= ColumnCount. 90 KeyColumnCount() int 91 92 // LaxKeyColumnCount returns the number of columns in the index that are 93 // part of its "lax" key. Lax keys follow the same rules as keys (sometimes 94 // referred to as "strict" keys), except that NULL values are treated as 95 // *not* equal to one another, as in the case for UNIQUE indexes. This means 96 // that two rows can appear to have duplicate values when one of those values 97 // is NULL. See the KeyColumnCount comment for more details and an example. 98 // 99 // The lax key columns are always a prefix of the key columns, where 100 // LaxKeyColumnCount <= KeyColumnCount. However, it is not required that an 101 // index have a separate lax key, in which case LaxKeyColumnCount equals 102 // KeyColumnCount. Here are the cases: 103 // 104 // PRIMARY KEY : lax key cols = key cols 105 // INDEX (not unique) : lax key cols = key cols 106 // UNIQUE INDEX, not-null cols: lax key cols = key cols 107 // UNIQUE INDEX, nullable cols: lax key cols < key cols 108 // 109 // In the first three cases, all strict key columns (and thus all lax key 110 // columns as well) are guaranteed to be encoded in the row's key (as opposed 111 // to in its value). Note that the third case, the UNIQUE INDEX columns are 112 // sufficient to form a strict key without needing to append the primary key 113 // columns (which are stored in the value). 114 // 115 // For the last case of a UNIQUE INDEX with at least one NULL-able column, 116 // only the lax key columns are guaranteed to be encoded in the row's key. 117 // The strict key columns (the primary key columns in this case) are only 118 // encoded in the row's key when at least one of the lax key columns has a 119 // NULL value. Therefore, whether the row's key contains all the strict key 120 // columns is data-dependent, not schema-dependent. 121 LaxKeyColumnCount() int 122 123 // Column returns the ith IndexColumn within the index definition, where 124 // i < ColumnCount. 125 Column(i int) IndexColumn 126 127 // Zone returns the zone which constrains placement of the index's range 128 // replicas. If the index was not explicitly assigned to a zone, then it 129 // inherits the zone of its owning table (which in turn inherits from its 130 // owning database or the default zone). In addition, any unspecified zone 131 // information will also be inherited. 132 // 133 // NOTE: This zone always applies to the entire index and never to any 134 // particular partition of the index. 135 Zone() Zone 136 137 // Span returns the KV span associated with the index. 138 Span() roachpb.Span 139 140 // PartitionByListPrefixes returns values that correspond to PARTITION BY LIST 141 // values. Specifically, it returns a list of tuples where each tuple contains 142 // values for a prefix of index columns (indicating a region of the index). 143 // Each tuple corresponds to a configured partition or subpartition. 144 // 145 // Note: this function decodes and allocates datums; use sparingly. 146 // 147 // Example: 148 // 149 // CREATE INDEX idx ON t(region,subregion,val) PARTITION BY LIST (region,subregion) ( 150 // PARTITION westcoast VALUES IN (('us', 'seattle'), ('us', 'cali')), 151 // PARTITION us VALUES IN (('us', DEFAULT)), 152 // PARTITION eu VALUES IN (('eu', DEFAULT)), 153 // PARTITION default VALUES IN (DEFAULT) 154 // ); 155 // 156 // PartitionByListPrefixes() returns 157 // ('us', 'seattle'), 158 // ('us', 'cali'), 159 // ('us'), 160 // ('eu'). 161 // 162 // The intended use of this function is for index skip scans. Each tuple 163 // corresponds to a region of the index that we can constrain further. In the 164 // example above: if we have a val=1 filter, instead of a full index scan we 165 // can skip most of the data under /us/cali and /us/seattle by scanning spans: 166 // [ - /us/cali ) 167 // [ /us/cali/1 - /us/cali/1 ] 168 // [ /us/cali\x00 - /us/seattle ) 169 // [ /us/seattle/1 - /us/seattle/1 ] 170 // [ /us/seattle\x00 - ] 171 // 172 PartitionByListPrefixes() []tree.Datums 173 174 // InterleaveAncestorCount returns the number of interleave ancestors for this 175 // index (or zero if this is not an interleaved index). Each ancestor is an 176 // index (usually from another table) with a key that shares a prefix with 177 // the key of this index. 178 // 179 // Each ancestor contributes one or more key columns; together these pieces 180 // form a prefix of an index key. 181 // 182 // The ancestors appear in the order they appear in an encoded key. This means 183 // they are always in the far-to-near ancestor order (e.g. 184 // grand-grand-parent, grand-parent, parent). 185 // 186 // 187 // Example: 188 // Index 1 -> /a/b 189 // Index 2 -> /a/b/c 190 // Index 3 -> /a/b/c/d 191 // 192 // Index 3 has two ancestors; the first is index 1 (contributing 2 key 193 // columns) and the second is index 2 (contributing 1 key column). 194 InterleaveAncestorCount() int 195 196 // InterleaveAncestor returns information about an ancestor index. 197 // 198 // numKeyCols is the number of key columns that this ancestor contributes to 199 // an encoded key. In other words: each ancestor has a shared key prefix 200 // with this index; numKeyCols is the difference the shared prefix length for 201 // this ancestor and the shared prefix length for the previous ancestor. 202 // See InterleaveAncestorCount for an example. 203 InterleaveAncestor(i int) (table, index StableID, numKeyCols int) 204 205 // InterleavedByCount returns the number of indexes (usually from other 206 // tables) that are interleaved into this index. 207 // 208 // Note that these indexes can themselves be interleaved by other indexes, but 209 // this list contains only those for which this index is a direct interleave 210 // parent. 211 InterleavedByCount() int 212 213 // InterleavedBy returns information about an index that is interleaved into 214 // this index; see InterleavedByCount. 215 InterleavedBy(i int) (table, index StableID) 216 } 217 218 // IndexColumn describes a single column that is part of an index definition. 219 type IndexColumn struct { 220 // Column is a reference to the column returned by Table.Column, given the 221 // column ordinal. 222 Column 223 224 // Ordinal is the ordinal position of the indexed column in the table being 225 // indexed. It is always >= 0 and < Table.ColumnCount. 226 Ordinal int 227 228 // Descending is true if the index is ordered from greatest to least on 229 // this column, rather than least to greatest. 230 Descending bool 231 } 232 233 // IsMutationIndex is a convenience function that returns true if the index at 234 // the given ordinal position is a mutation index. 235 func IsMutationIndex(table Table, ord IndexOrdinal) bool { 236 return ord >= table.IndexCount() 237 }