diff --git a/hetu-docs/en/admin/properties.md b/hetu-docs/en/admin/properties.md index e165f086d..852a6e106 100644 --- a/hetu-docs/en/admin/properties.md +++ b/hetu-docs/en/admin/properties.md @@ -536,7 +536,11 @@ Heuristic index is external index module that which can be used to filter to out > - **Type** `string` > -> This property defines the filesystem profile used to read and write index. The corresponding profile must exist in `etc/filesystem`. For example, if this property is set as `hetu.heuristicindex.filter.indexstore.filesystem.profile=index-hdfs1`, a profile describing this filesystem access `index-hdfs1.properties` must be created in `etc/filesystem` with necessary information including authentication type, config, and keytabs (if applicable). +> This property defines the filesystem profile used to read and write index. The corresponding profile must exist in `etc/filesystem`. For example, if this property is set as `hetu.heuristicindex.filter.indexstore.filesystem.profile=index-hdfs1`, a profile describing this filesystem access `index-hdfs1.properties` must be created in `etc/filesystem` with necessary information including authentication type, config, and keytabs (if applicable). +> +> `LOCAL` filesystem type should only be used during testing or in single node clusters. +> +> `HDFS` filesystem type should be used in production in order for the index to be accessible by all nodes in the cluster. All nodes should be configured to use the same filesystem profile. ## Execution Plan Cache Properties diff --git a/hetu-docs/en/images/index-decision.png b/hetu-docs/en/images/index-decision.png new file mode 100644 index 000000000..b89d36f58 Binary files /dev/null and b/hetu-docs/en/images/index-decision.png differ diff --git a/hetu-docs/en/indexer/bitmap.md b/hetu-docs/en/indexer/bitmap.md index 5f2dadd61..8f9e5a851 100644 --- a/hetu-docs/en/indexer/bitmap.md +++ b/hetu-docs/en/indexer/bitmap.md @@ -1,19 +1,42 @@ # Bitmap Index -## Use cases +Bitmap Index utilizes Bitmaps. The size of the index increases as the number +of unique values in the column increases. For example, a column like gender +will have a small size. Whereas a column like ID will have an extremely +large size (not recommended). -Bitmap Index is used for filtering data read from ORC files and is used only by the **worker** nodes +Note: Bitmap Index can additionally benefit when ORC predicate pushdown is enabled. +This can be enabled by setting `hive.orc-predicate-pushdown-enabled=true` +in `hive.properties` or setting the session using `set session hive.orc_predicate_pushdown_enabled=true;`. +Setting this to true will improve improve the performance of queries that utilize Bitmap Index. +See [Properties](../admin/properties.md) for details. -- If this index exists on a column which is part of a predicate in the query, the performance may be improved while reading the ORC files. +## Filtering -For example, if an index exists on column `country` and the query is +1. Bitmap Index is used on workers for filtering rows when reading ORC files. -``` sql -select * from table where country="China" +## Selecting column for Bitmap Index + +Bitmap Index works on columns that have a low cardinality (i.e. few unique values), +such as a Gender column. + +## Supported operators + + = Equality + +## Examples + +Creating index: +```sql +create index idx using bitmap on hive.hindex.users (gender); +create index idx using bitmap on hive.hindex.users (gender) where regionkey=1; +create index idx using bitmap on hive.hindex.users (gender) where regionkey in (3, 1); ``` -- This index works best if the column's values are not too distinct (e.g. country) and are distributed. - -For example, assume that the table stores information about where users are from and the table data is in 10 files. There maybe be several users from a particular country, so each file will have some users from the country. If we create a bitmap index on the country column, we can perform filtering early on while reading the data files. i.e. the predicate is pushed down to the reading of the file. Without this index, all the data files will need to be read into memory as Pages and then the filtering would happen. With the index, we can ensure that the Pages already only contain the rows matching the predicate. This can help reduce the memory and CPU usage and can result in improved performance when many concurrent queries are running. +* assuming users table is partitioned on `regionkey` +Using index: +```sql +select name from hive.hindex.users where gender="female" +``` \ No newline at end of file diff --git a/hetu-docs/en/indexer/bloom.md b/hetu-docs/en/indexer/bloom.md index f67129f35..eb83e959f 100644 --- a/hetu-docs/en/indexer/bloom.md +++ b/hetu-docs/en/indexer/bloom.md @@ -1,22 +1,48 @@ # Bloom Index -## Use cases +Bloom Index utilizes Bloom Filters and index size will be fairly small. -Bloom Index is used for split filtering, and is used only by the **coordinator** nodes. +## Filtering -- If this index exists on a column which is part of a predicate in the query, openLooKeng may be able to improve performance by filtering scheduled splits. +1. Bloom Index is used on coordinator for filtering splits during scheduling +2. Bloom Index is used on workers for filtering Stripes when reading ORC files -For example, if an index exists on column `id` and the query is: +## Selecting column for Bloom Index +Bloom Index works on columns that have high cardinality (i.e. unique values), +such as an ID column. + +## Supported operators + + = Equality + +## Configurations + +### `bloom.fpp` + +> - **Type:** `Double` +> - **Default value:** `0.001` +> +> Changes the FPP (false positive probability) value of the Bloom filter. +> Making this value smaller will increase the effectiveness of the index but +> will also increase the index size. The default value should be sufficient +> in most usecases. If the index is too large, this value can be increased +> e.g. 0.05. + +## Examples + +Creating index: ```sql -select * from table where id=12345 +create index idx using bloom on hive.hindex.users (id); +create index idx using bloom on hive.hindex.users (id) where regionkey=1; +create index idx using bloom on hive.hindex.users (id) where regionkey in (3, 1); +create index idx using bloom on hive.hindex.users (id) WITH ("bloom.fpp" = '0.001'); ``` +* assuming users table is partitioned on `regionkey` - -- Bloom index works best if the column's values are unique (e.g. userid) and are not too distributed. - -For example, assume the tables stores information about users and the table data is in 10 files. For a given userid, only one file will contain the data. Therefore creating an index on userid will help us to filter out 9 out of the 10 files at scheduling time and will save significant IO time that would've therwise been used to read each of the files. - -*Tip: if possible, it is recommended to sort the data on the column being indexed.* \ No newline at end of file +Using index: +```sql +select name from hive.hindex.users where id=123 +``` \ No newline at end of file diff --git a/hetu-docs/en/indexer/btree.md b/hetu-docs/en/indexer/btree.md new file mode 100644 index 000000000..10f4f02f3 --- /dev/null +++ b/hetu-docs/en/indexer/btree.md @@ -0,0 +1,52 @@ +# BTree Index + +BTree Index utilizes the B-Tree data structure. +The size of the index increases as the number +of unique values in the column increases. + +## Filtering + +1. BTree Index is used on coordinator for filtering splits during scheduling + +## Selecting column for BTree Index + +BTree Index works on columns that have high cardinality (i.e. unique values), +such as an ID column, additionally it requires that the table be partitioned, +e.g. by date. + +When selecting between BTree Index, the following should be considered: +- Bloom index only supports `=` +- Btree index requires the table to be partitioned +- Bloom index is probabilistic, whereas Btree index is deterministic. This means Btree will perform better filtering. +- Btree index size will be larger than Bloom index + +## Supported operators + + = Equality + > Greater than + >= Greater than or equal + < Less than + <= Less than or equal + BETWEEN Between range + IN IN set + +## Examples + +Creating index: +```sql +create index idx using btree on hive.hindex.orders (orderid) with (level=partition) where orderDate='01-10-2020' ; +create index idx using btree on hive.hindex.orders (orderid) with (level=partition) where orderDate in ('01-10-2020', '01-10-2020'); +``` + +* assuming orders table is partitioned on `orderDate`; table must be partitioned + +Using index: +```sql +select * from hive.hindex.orders where orderid=12345 +select * from hive.hindex.orders where orderid>12345 +select * from hive.hindex.orders where orderid<12345 +select * from hive.hindex.orders where orderid>=12345 +select * from hive.hindex.orders where orderid<=12345 +select * from hive.hindex.orders where orderid between (10000, 20000) +select * from hive.hindex.orders where orderid in (12345, 7890) +``` \ No newline at end of file diff --git a/hetu-docs/en/indexer/hindex-statements.md b/hetu-docs/en/indexer/hindex-statements.md new file mode 100644 index 000000000..c83f4dcb0 --- /dev/null +++ b/hetu-docs/en/indexer/hindex-statements.md @@ -0,0 +1,68 @@ + + +# Usage + +Index can be managed using any of the supported clients, such as hetu-cli located under the `bin` directory in the installation. + + +## CREATE +To create an index you can run sql statements of the form: +```roomsql +CREATE INDEX [ IF NOT EXISTS ] index_name +USING [ BITMAP | BLOOM | BTREE | MINMAX ] +ON tbl_name (col_name) +WITH ( "level" = ['STRIPE', 'PARTITION'], "bloom.fpp" = '0.001', [, …] ) +WHERE predicate; +``` + +- `WHERE` predicate can be used to create index on select partition(s) +- `WITH` can be used to specify index properties or index level. See individual index documentation to support properties. +- `"level"='STRIPE'` if not specified + +If the table is partitioned, you can specify a single partition to create an index on, or an in-predicate to specify multiple partitions: + +```roomsql +CREATE INDEX index_name USING bloom ON hive.schema.table (column1); +CREATE INDEX index_name USING bloom ON hive.schema.table (column1) WITH ("bloom.fpp"="0.01") WHERE p=part1; +CREATE INDEX index_name USING bloom ON hive.schema.table (column1) WHERE p in (part1, part2, part3); +``` + +## SHOW + +To show all indexes or a specific index_name: +```roomsql +SHOW INDEX; +SHOW INDEX index_name; +``` + +## DROP + +To delete an index by name: +```roomsql +DROP INDEX index_name +WHERE predicate; +``` + +- `WHERE` predicate be used to delete index for specific partition(s). However, if index was initially created on the entire table, it is not possible to delete index for a single partition. + +```roomsql +DROP INDEX index_name where p=part1; +``` + +Note: dropped index will be removed from cache after a few seconds, so you may still see the next few queries still using the index. + + +## Notes on resource usage + +### Disk usage +Heuristic index uses the local temporary directory (default `/tmp` on linux) while creating and processing indexes while running. +Therefore, the temporary directory should have sufficient space. To change the temporary directory set the following property in `etc/jvm.config`: + +``` +-Djava.io.tmpdir=/path/to/another/dir +``` + +The size of the index depends closely on the column properties such as number of unique values. +As a rough estimate, the available temporary disk space should be table size divided by the number of columns. +For example, e.g. for a table of 100GB with five mostly unique columns, 25GB of temporary disk space should be available. + diff --git a/hetu-docs/en/indexer/indexer-cli.md b/hetu-docs/en/indexer/indexer-cli.md deleted file mode 100644 index 9a80462e2..000000000 --- a/hetu-docs/en/indexer/indexer-cli.md +++ /dev/null @@ -1,97 +0,0 @@ - - -# Index Command Line Interface - -## Usage - -The indexer can be utilized using the hetu-cli executable located under the `bin` directory in the installation. - -To create an index you can run sql queries of the form: -```roomsql -CREATE INDEX [ IF NOT EXISTS ] index_name -USING [ BITMAP | BLOOM | MINMAX ] -ON tbl_name (col_name) -WITH ( "bloom.fpp" = '0.001', [, …] ) -WHERE predicate; -``` - -To show all indexes or a specific index_name: -```roomsql -SHOW INDEX; -SHOW INDEX index_name; -``` - -To delete an index by name: -```roomsql -DROP INDEX index_name; -``` - -## Examples - -Path white list:["/tmp", "/opt/hetu", "/opt/openlookeng", "/etc/hetu", "/etc/openlookeng", current workspace] - -`etc` directory includes config.properties, and --config should specify an absolute path, -the path should be children directory of Path white list - -### Create index - -``` shell -$ java -jar ./hetu-cli-*.jar --config /xxx/etc --execute 'CREATE INDEX index_name USING bloom ON hive.schema.table (column1) WITH ("bloom.fpp"="0.01", verbose=true) WHERE p=part1' -``` - -### Show index - -``` shell -$ java -jar ./hetu-cli-*.jar --config /xxx/etc --execute "SHOW INDEX index_name" -``` - -### Drop index - -``` shell -$ java -jar ./hetu-cli-*.jar --config /xxx/etc --execute "DROP INDEX index_name" -``` - -*Note*: Dropping an index will not remove the cached index from hetu server. This means the index may still be used until it expires from cache based on `hetu.heuristicindex.filter.cache.ttl` value or hetu server is restarted. - -## Notes on resource usage - -### Memory - -By default the default JVM MaxHeapSize will be used (`java -XX:+PrintFlagsFinal -version | grep MaxHeapSize`). For improved performance, it is recommended to increase the MaxHeapSize. This can be -done by setting -Xmx value: - -*Note*: This should be done before executing the hetu-cli. -``` shell -export JAVA_TOOL_OPTIONS="-Xmx100G" -``` - -In this example the MaxHeapSize will be set to 100G. - -### Disk usage -Heuristic index uses local temporary storage to create the indices then tar them onto hdfs. Therefore, it requires enough local disk space where the temporary directory (e.g. `/tmp` for linux) is mounted. Users can specify the temporary directory for the index writer to use if the default one is mounted on the disk with insufficient space. To do this, run the cli with `-Djava.io.tmpdir` flag: - -```bash -java -Djava.io.tmpdir=/path/to/another/dir -jar ./hetu-cli-*.jar -``` - -We have a rough estimation of how much disk space the indices may take for bloom index. It is linear to the original size of the table on which the index is created, and is linear to the negative logarithmic of `fpp`. The smaller fpp and larger dataset, the bigger index will be created: - -index size = -log(fpp) * table size on disk * C - -The coefficient C varies depending on some other factors, which are not as significant and usually change less, such as how much the selected column weighs in the table. As a typical value, its around 0.04. Therefore, for a typical table with a few columns which is 100GB on hdfs, creating a bloom index with `fpp=0.001` on a column will take about 12GB space, while it takes around 16GB if `fpp` is set at `0.0001`. - -### Indexing in parallel - -If creating the index for a large table is too slow on one machine, you can create an index for different partitions in parallel on different machines. Just make sure they are assigned with different partitions. For example: - -On machine 1: - -``` bash -$ java -jar ./hetu-cli-*.jar --config /xxx/etc --execute 'CREATE INDEX index_name USING bloom ON hive.schema.table (column1) WITH ("bloom.fpp"="0.01") WHERE p=part1' -``` - -On machine 2: - -``` shell -$ java -jar ./hetu-cli-*.jar --config /xxx/etc --execute 'CREATE INDEX index_name USING bloom ON hive.schema.table (column1) WITH ("bloom.fpp"="0.01") WHERE p=part2' -``` diff --git a/hetu-docs/en/indexer/minmax.md b/hetu-docs/en/indexer/minmax.md index f99aefefb..65a02d644 100644 --- a/hetu-docs/en/indexer/minmax.md +++ b/hetu-docs/en/indexer/minmax.md @@ -1,22 +1,44 @@ -# Minmax Index +# MinMax Index -## Use cases +MinMax simply keeps tracks of the largest and smallest value. +The size of the index is extremely small. +However, this index will only be useful if the table is sorted +on the indexed column. -MinMax Index is used for split filtering, and is used only by the **coordinator** nodes. +## Filtering -If this index exists on a column which is part of a predicate in the query, the engine may be able to improve performance by filtering scheduled splits similar to Bloom Index. +1. MinMax Index is used on coordinator for filtering splits during scheduling -For example if an index exists on column +## Selecting column for MinMax Index -`age` +MinMax Index will only work well on columns on which the table is sorted. +For example, ID or age. -and the query is +## Supported operators + = Equality + > Greater than + >= Greater than or equal + < Less than + <= Less than or equal + +## Examples + +Creating index: ```sql -select * from table where age > 50 +create index idx using minmax on hive.hindex.users (age); +create index idx using minmax on hive.hindex.users (age) where regionkey=1; +create index idx using minmax on hive.hindex.users (age) where regionkey in (3, 1); ``` +* assuming users table is partitioned on `regionkey` - -*Tip: sorting the data on the index column will provide the best results* \ No newline at end of file +Using index: +```sql +select name from hive.hindex.users where age=20 +select name from hive.hindex.users where age>20 +select name from hive.hindex.users where age<20 +select name from hive.hindex.users where age>=20 +select name from hive.hindex.users where age<=20 +``` \ No newline at end of file diff --git a/hetu-docs/en/indexer/new-index.md b/hetu-docs/en/indexer/new-index.md new file mode 100644 index 000000000..4f4396f9e --- /dev/null +++ b/hetu-docs/en/indexer/new-index.md @@ -0,0 +1,52 @@ +# Adding your own Index Type + +## Basic ideas + +### ID + +Each index type must have an `ID`, which is a unique identifier and the canonical name of an index type used in CLI, server config, file path, etc. + +The `getID()` method in the `Index` interface returns the ID of this index type to any infrastructure that uses it. + +### Level + +A heuristic index stores additional and usually partial information of a dataset in a more compact way to speed up lookups in various ways. Therefore, each index must +have a domain on which it is applied. For instance, if an index marks the max value of a data set, we must know how big the data set is when we define the "max" value (i.e. +it can be the max of a group of rows, a data partition, or even a whole table). When a new index type is created, it must implement a method `Set getSupportedIndexLevels();` +which returns the data set level it can support. The levels are defined as an enum in `Index` interface. + +## Interface overlook + +### Indexing methods + +Apart from the methods metioned above, this section gives a quick guide on the most important methods needed to create a new index type. For the complete +document on `Index` interface, please refer to the Java Doc of the source code. + +There are two main functionalities in the `Index` interface: + +```java +boolean matches(Object expression) throws UnsupportedOperationException; + + Iterator lookUp(Object expression) throws UnsupportedOperationException; +``` + +The first `matches()` method takes an expression, and returns if a predicate (the expression) can hold on a specific **Level** of data. For example, if an index records +the max value of an integer column, it could easily tell if `col_val > 5` can hold by comparing `5` to the max value. + +The second `lookUp()` method is optional. Instead of only returning a boolean about whether a predicate can hold, it returns an iterator of all the possible positions +where the data can be found. An index should always have the same result on `matches()` and `lookUp().hasNext()`. + +### Adding and persisting values + +The following methods are used to add values to the index and persist index objects onto disk: + +```java +boolean addValues(Map> values) throws IOException; + +Index deserialize(InputStream in) throws IOException; + +void serialize(OutputStream out) throws IOException; +``` + +The usage of them are pretty straightforward. A good example to help understand their usage is the source code of `MinMaxIndex`, where adding values is just to +update the `max` and `min` variables according to the input number, and `serialize()/deserialize()` \ No newline at end of file diff --git a/hetu-docs/en/indexer/overview.md b/hetu-docs/en/indexer/overview.md index e652aba3f..cca04b8fd 100644 --- a/hetu-docs/en/indexer/overview.md +++ b/hetu-docs/en/indexer/overview.md @@ -1,5 +1,5 @@ -# openLooKeng Heuristic Indexer +# openLooKeng Heuristic Index ## Introduction @@ -12,73 +12,168 @@ The Heuristic Indexer allows creating indexes on existing data but stores the in - New index types not supported by the underlying data source can be created - Index data does not use the storage space of the data source + ## Use cases -Currently, heuristic indexer is supported on hive ORC data source to reduce the number of splits or rows read. +**Currently, Heuristic Index is only supports the Hive connector with +tables using ORC storage format.** ### 1. Filtering scheduled Splits during query execution -When the engine needs to schedule a TableScan operation, it schedules Splits on the workers. These Splits are responsible for reading a portion of the source data. However, not all Splits will return data if a predicate is applied. +*Index types supported: Bloom Index, Btree Index, MinMax Index* + +When the engine needs to read data from a data source it schedules Splits. +However, not all Splits will return data if a predicate is applied. + +For example: `select * from test_base where j1='070299439'` By keeping an external index for the predicate column, the Heuristic Indexer can determine whether each split contains the values being searched for and only schedule the read operation for the splits which possibly contain the value. ![indexer_filter_splits](../images/indexer_filter_splits.png) -### 2. Filtering Block early when reading ORC files +### 2. Filtering Stripes when reading ORC files -When data needs to be read from an ORC file, the ORCRecordReader is used. This reader reads data from Stripes as batches (e.g. 1024 rows), which then form Pages. However, if a predicate is present, not all entries in the batch are required, some may be filtered out later by the Filter operator. +*Index types supported: Bloom Index, MinMax Index* -By keeping an external bitmap index for the predicate column, the Heuristic Indexer can filter out rows which do not match the predicates before the Filter operator is even applied. +Similar to Split filtering above, when using the Hive connector to read ORC tables, +Stripes can be filtered out based on the specified predicate. This reduces the amount +of data read and improves query performance. -## Example tutorial +### 3. Filtering rows when reading ORC files -This section gives a short tutorial which introduces the basic usage of heuristic index through a sample query. +*Index types supported: Bitmap Index* -### Identify a type of index on a column that can help +Going one level lower, once the rows are read, they must be filtered if a predicate is present. +This involves reading rows and then using the Filter operator to discard +rows that do not match the predicate. -For a query: +By creating a Bitmap Index for the predicate column, the Heuristic Indexer will only read +rows which match the predicate, before the Filter operator is even applied. This can reduce +memory and cpu usage and result in improved query performance, especially at higher concurrency. - SELECT * FROM table1 WHERE id="abcd1234"; - -A bloom index on id column can significantly decrease the splits to read when scanning table1. -We will use this example throughout this tutorial. +## Getting started -### Configure indexer settings +This section gives a short tutorial which introduces the basic usage of Heuristic Index through a sample query. +For a complete list of configuration properties see [Properties](../admin/properties.md). + +### 1. Configure indexer settings In `etc/config.properties`, add these lines: -Path white list:["/tmp", "/opt/hetu", "/opt/openlookeng", "/etc/hetu", "/etc/openlookeng", current workspace] - -Notice:avoid to choose root directory; ../ can't include in path; if you config node.date_dir, then the current workspace is the parent of node.data_dir; -otherwise, the current workspace is the openlookeng server's directory. - hetu.heuristicindex.filter.enabled=true - hetu.heuristicindex.filter.cache.max-memory=2GB + hetu.heuristicindex.filter.cache.max-memory=10GB hetu.heuristicindex.indexstore.uri=/opt/hetu/indices hetu.heuristicindex.indexstore.filesystem.profile=index-store-profile - -Then create an hdfs client profile in `etc/filesystem/index-store-profile.properties`, where `index-store-profile` is what specified above as the file name: + +Path whitelist:`["/tmp", "/opt/hetu", "/opt/openlookeng", "/etc/hetu", "/etc/openlookeng", current workspace]` + +**Note**: +- `LOCAL` filesystem type should only be used in testing or single node clusters. +- `HDFS` filesystem type should be used in production in order for the index to be accessible by all nodes in the cluster. +- All nodes should be configured to use the same filesystem profile. +- Heuristic Index can be disabled while the engine is running by setting: `set session heuristicindex_filter_enabled=false;` + +Filesystem profile file should be placed at `etc/filesystem/index-store-profile.properties`, +where `index-store-profile` is the name referenced above in `config.properties`: fs.client.type=hdfs hdfs.config.resources=/path/to/core-site.xml,/path/to/hdfs-site.xml hdfs.authentication.type=NONE fs.hdfs.impl.disable.cache=true -If the hdfs cluster enables kerberos authentication, additional configs `hdfs.krb5.conf.path, hdfs.krb5.keytab.path, hdfs.krb5.principal` needs to be configured. +If the kerberos authentication is enabled, additional configs `hdfs.krb5.conf.path`, +`hdfs.krb5.keytab.path`, and `hdfs.krb5.principal` must be provided. -In this example we use a hdfs cluster to store the index files, which can be shard across different hetu servers. If you would like to use local disk to store index, simply change `index-store-profile.properties` to: +With Heuristic Indexer configured, start the engine. - fs.client.type=local +### 2. Identify a column to create index on + +For a query like: + + SELECT * FROM hive.schema.table1 WHERE id="abcd1234"; + +Where `id` is unique, a Bloom Index on can significantly decrease the splits to read +when scanning table1. + +### 3. Create index + +To create index run the following statement: + + CREATE INDEX index_name USING bloom ON table1 (column); -Note that you may create multiple filesystem profiles in `etc/filesystem`, several for different hdfs clusters and one for local, so you can easily switch between them by just changing the value of `hetu.heuristicindex.indexstore.filesystem.profile`. +### 4. Run query -### Create index +After index is created, run the query; index will start loading in the background. +Subsequent queries will utilize the index to reduce the amount of data read + and query performance will be improved. -To write index to the indexstore specified above, just change directory to your hetu installation's `bin` folder, then run: - java -jar ./hetu-cli-*.jar --config --execute 'CREATE INDEX index_name USING bloom ON table1 (column)' +## Index Statements + +See [Heuristic Index Statements](./hindex-statements.md). + +----- + +## Supported Index Types + +| Index ID | Filtering type | Best Column type | Supported query operators | Notes | Example | +|----------|-----------------|--------------------------------------------|---------------------------------------|---------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [Bloom](./bloom.md) | Split
Stripe | High cardinality
(such as an ID column) | `=` `IN` | | `create index idx using bloom on hive.hindex.users (id);`
`select name from hive.hindex.users where id=123` | +| [Btree](./btree.md) | Split | High cardinality
(such as an ID column) | `=` `>` `>=` `<` `<=` `IN` `BETWEEN` | Table must be partitioned | `create index idx using btree on hive.hindex.users (id) where regionkey IN (1,4) with ("level"='partition')`
(assuming table is partitioned on regionkey)
`select name from hive.hindex.users where id>123` | +| [MinMax](./minmax.md) | Split
Stripe | Column which table is sorted on | `=` `>` `>=` `<` `<=` | | `create index idx using bloom on hive.hindex.users (age);`
(assuming users is sorted by age)
`select name from hive.hindex.users where age>25` | +| [Bitmap](./bitmap.md) | Row | Low cardinality
(such as Gender column) | `=` `IN` | | `create index idx using bitmap on hive.hindex.users (gender);`
`select name from hive.hindex.users where gender='female'` | + +**Note:** unsupported operators will still function correctly but will not benefit from the index. + + +## Choosing Index Type + +The Heuristic Indexer helps with queries where data is being filtered by a predicate. +Identify the column on which data is being filtered and use the decision flowchart to +help decide what type of index will work best. + +Cardinality means the number of distinct values in the column relative to +number of total rows. For example, an `ID` column has a high cardinality +because IDs are unique. Whereas `employeeType` will have low cardinality +because there are likely only a few different types (e.g. Manager, Developer, +Tester). + +![index-decision](../images/index-decision.png) + +Example queries: + +1. `SELECT id FROM employees WHERE site = 'lab';` + + In this query `site` has a low cardinality (i.e. not many sites) so **Bitmap Index** will help. + +2. `SELECT * FROM visited WHERE id = '34857' AND date < '2020-01-01';` + + In this query `id` has a high cardinality (i.e. IDs are likely unique) + and table is partitioned on `date` so **Btree Index** will help. -### Run query +3. `SELECT * FROM salaries WHERE salary > 50251.40;` -After this is finished, run the query on hetu server again, and it will start loading index in the background. Keep running the same query while it's loading, then you should see decrease in the number of splits processed, which finally goes down to a rather small value. + In this query `salary` has a high cardinality (i.e. salary of employees + will slightly vary) and assuming `salaries` table is sorted on `salary`, + **MinMax Index** will help. + +4. `SELECT * FROM assets WHERE id = 50;` + + In this query `id` has a high cardinality (i.e. IDs are likely unique) + but the table is not partitioned, so **Bloom Index** will help. + +5. `SELECT * FROM phoneRecords WHERE phone='1234567890' and type = 'outgoing' and date > '2020-01-01';` + + In this query `phone` has a high cardinality (i.e. there are many phone numbers, even if they + made multiple calls), `type` has low cardinality (only outgoing or incoming), + and the data is partitioned on date. Creating a **Btree Index** on `phone` + and a **Bitmap Index** on `type` will help. + +## Adding your own Index Type + +See [Adding your own Index Type](./new-index.md). + +## Access Control + +See [Built-in System Access Control](../security/built-in-system-access-control.md). diff --git a/hetu-docs/en/security/built-in-system-access-control.md b/hetu-docs/en/security/built-in-system-access-control.md index 4ed1dde5a..1b39693a1 100644 --- a/hetu-docs/en/security/built-in-system-access-control.md +++ b/hetu-docs/en/security/built-in-system-access-control.md @@ -181,4 +181,31 @@ For example, if you want to allow only the user `admin` and `alice` to update th } ] } +``` + +### Heuristic Index Rules + +The rules govern the Heuristic Index operations particular users can perform. + +Each rule is composed of the following fields: + +- `user` (required): regex to match against user name. Defaults to `.*`. +- `privileges` (optional): list of privileges granted to user (`ALL`, `SHOW`, `CREATE`, `DROP`, `RENAME`, and `UPDATE`). Defaults to `ALL`. + +For example, here user `tom` can only execute `SHOW INDEX` or `CREATE INDEX` statements. +But user `admin` can execute all statements `CREATE INDEX`, `SHOW INDEX`, `DROP INDEX`, etc. + +```json +{ + "indexAccess": [ + { + "user": "tom", + "privileges": ["SHOW", "CREATE"] + }, + { + "user": "admin", + "privileges": ["ALL"] + } + ] +} ``` \ No newline at end of file diff --git a/hetu-docs/zh/admin/properties.md b/hetu-docs/zh/admin/properties.md index df852e777..51e9c62cf 100644 --- a/hetu-docs/zh/admin/properties.md +++ b/hetu-docs/zh/admin/properties.md @@ -1,578 +1,581 @@ -# 属性参考 - -本节将介绍最重要的配置属性,这些属性可用于调优openLooKeng或在需要时更改其行为。 - -## 通用属性 - -### `join-distribution-type` - -> - **类型:** `string` -> - **允许值:** `AUTOMATIC`,`PARTITIONED`,`BROADCAST` -> - **默认值:** `PARTITIONED` -> -> 要使用的分布式联接的类型。 设置为`PARTITIONED`时,openLooKeng将使用哈希分布式联接。 当设置为`BROADCAST`时,将向集群中所有从左表获得数据的节点广播右表。分区联接要求使用联接键的哈希重分布这两个表。这可能比广播联接慢(有时极慢),但允许更大的联接。特别是如果右表比左表小得多,则广播联接将更快。 但是广播联接要求联接右侧过滤后的表适合每个节点的内存,而分布式联接只需要适合所有节点的分布式内存。当设置为`AUTOMATIC`时,openLooKeng将基于成本决定哪种分布类型是最优的。还将考虑将左右输入切换到联接。 在`AUTOMATIC`模式中,如果无法计算成本,例如表没有统计信息,openLooKeng将默认哈希分布式联接。也可以使用`join_distribution_type`会话属性在每个查询基础上指定。 - -### `redistribute-writes` - -> - **类型:** `boolean` -> - **默认值:** `true` -> -> 此属性允许在写入数据之前重新分布数据。这可以通过在集群中的节点间散列数据来消除数据倾斜带来的性能影响。当已知输出数据集没有发生倾斜时,可以停用数据分布,以避免在网络上散列和重分布所有数据的开销。也可以使用`redistribute_writes`会话属性在每个查询基础上指定。 - -### `stack-trace-visible` - -> - **类型:** `boolean` -> - **允许值:** `true`, `false` -> - **默认值:** `false` -> -> 此属性控制系统是否能够在CLI、WEB UI等对外展示系统出现Exception时的代码调用栈. 当设置为`true`时对外展示给所有用户,设置为`false`或者采用默认设置,不展示给任何用户。 - -## http 安全头部属性 - -### `http-header.content-security-policy` - -> - **类型:** `string` -> - **默认值:** `object-src 'none'` -> -> 此属性设置 `content-security-policy` 设置相关值。 - -### `http-header.referrer-policy` - -> - **类型:** `string` -> - **默认值:** `strict-origin-when-cross-origin` -> -> 此属性设置 `referrer-policy` 设置相关值。 - -### `http-header.x-content-type-options` - -> - **类型:** `string` -> - **默认值:** `nosniff` -> -> 此属性设置 `content-security-policy` 设置相关值。 - -### `http-header.x-frame-options` - -> - **类型:** `string` -> - **默认值:** `deny` -> -> 此属性设置 `content-security-policy` 设置相关值。 - -### `http-header.x-permitted-cross-domain-policies` - -> - **类型:** `string` -> - **默认值:** `master-only` -> -> 此属性设置 `x-permitted-cross-domain-policies` 设置相关值。 - -### `http-header.x-xss-protection` - -> - **类型:** `string` -> - **默认值:** `1; mode=block` -> -> 此属性设置 `http-header.x-xss-protection` 设置相关值。 - -## 内存管理属性 - -### `query.max-memory-per-node` - -> - **类型:** `data size` -> - **默认值:** `JVM max memory * 0.1` -> -> 此属性是查询在工作节点上可以使用的最大用户内存量。用户内存是在执行期间为用户查询直接归属或可控制的事物分配的。例如,在执行期间构建的哈希表使用的内存、排序期间使用的内存等。当任何工作节点上的查询的用户内存分配达到此限制时,该工作节点将被杀死。 - -### `query.max-total-memory-per-node` - -> - **类型:** `data size` -> - **默认值:** `JVM max memory * 0.3` -> -> 此属性是查询在工作节点上可以使用的最大用户和系统内存量。系统内存是在执行期间为用户查询无法直接归属或可控制的事物分配的。例如,由读取器、写入器、网络缓冲区等分配的内存。当任何工作节点上的查询所分配的用户和系统内存的总和达到此限制时,该工作节点将被杀死。`query.max-total-memory-per-node`的值必须大于`query.max-memory-per-node`。 - -### `query.max-memory` - -> - **类型:** `data size` -> - **默认值:** `20GB` -> -> 此属性是查询在整个集群上可以使用的最大用户内存量。用户内存是在执行期间为用户查询直接归属或可控制的事物分配的。例如,在执行期间构建的哈希表使用的内存、排序期间使用的内存等。当一个跨所有工作节点的查询的用户内存分配达到此限制时,该工作节点将被杀死。 - -### `query.max-total-memory` - -> - **类型:** `data size` -> - **默认值:** `query.max-memory * 2` -> -> 此属性是查询在整个集群上可以使用的最大用户和系统内存量。系统内存是在执行期间为用户查询无法直接归属或可控制的事物分配的。例如,由读取器、写入器、网络缓冲区等分配的内存。当一个跨所有工作节点的查询所分配的用户和系统内存的总和达到此限制时,该工作节点将被杀死。`query.max-total-memory`的值必须大于`query.max-memory`。 - -### `memory.heap-headroom-per-node` - -> - **类型:** `data size` -> - **默认值:** `JVM max memory * 0.3` -> -> 此属性是在JVM堆中为openLooKeng不跟踪的分配留作裕量/缓冲区的内存量。 - -## 溢出属性 - -### `experimental.spill-enabled` - -> - **类型:** `boolean` -> - **默认值:** `false` -> -> 尝试将内存溢出到磁盘,以避免超出查询的内存限制。 -> -> 溢出是将内存卸载到磁盘。此过程允许内存占用大的查询,代价是执行时间变慢。聚合、联接(内联接和外联接)、排序和窗口函数支持溢出。此属性不会减少其他联接类型所需的内存使用。 -> -> 注意,这是一个实验特性,应谨慎使用。 -> -> 此配置属性可由`spill_enabled`会话属性重写。 - -### `experimental.spill-order-by` - -> - **类型:** `boolean` -> - **默认值:** `true` -> -> 尝试将内存溢出到磁盘,以避免在运行排序运算符时超出查询的内存限制。此属性必须与`experimental.spill-enabled`属性一起使用。 -> -> 此配置属性可由`spill_order_by`会话属性重写。 - -### `experimental.spill-window-operator` - -> - **类型:** `boolean` -> - **默认值:** `true` -> -> 尝试将内存溢出到磁盘,以避免在运行窗口运算符时超出查询的内存限制。此属性必须与`experimental.spill-enabled`属性一起使用。 -> -> 此配置属性可由`spill_window_operator`会话属性重写。 - -### `experimental.spiller-spill-path` - -> - **类型:** `string` -> - **无默认值。** 启用溢出时必须设置。 -> -> 溢出内容写入的目录。该属性可以是一个逗号分隔的列表,以同时溢出到多个目录,这有助于利用系统中安装的多个驱动器。 -> -> 不建议溢出到系统驱动器上。最重要的是,不要溢出到写入JVM日志的驱动器,因为磁盘过度使用可能导致JVM长时间暂停,从而导致查询失败。 - -### `experimental.spiller-max-used-space-threshold` - -> - **类型:** `double` -> - **默认值:** `0.9` -> -> 如果指定溢出路径的磁盘空间使用率高于此阈值,则该溢出路径将不适用于溢出。 - -### `experimental.spiller-threads` - -> - **类型:** `integer` -> - **默认值:** `4` -> -> 溢出线程数。如果默认值不能使底层溢出设备饱和(例如,在使用RAID时),增大该值。 - -### `experimental.max-spill-per-node` - -> - **类型:** `data size` -> - **默认值:** `100 GB` -> -> 单个节点上所有查询使用的最大溢出空间。 - -### `experimental.query-max-spill-per-node` - -> - **类型:** `data size` -> - **默认值:** `100 GB` -> -> 单个查询在单个节点上使用的最大溢出空间。 - -### `experimental.aggregation-operator-unspill-memory-limit` - -> - **类型:** `data size` -> - **默认值:** `4 MB` -> -> 取消溢出单个聚合运算符实例所使用的内存限制。 - -### `experimental.spill-compression-enabled` - -> - **类型:** `boolean` -> - **默认值:** `false` -> -> 为溢出到磁盘的页面启用数据压缩。 - -### `experimental.spill-encryption-enabled` - -> - **类型:** `boolean` -> - **默认值:** `false` -> -> 允许使用随机生成的密钥(每个溢出文件)来加密和解密溢出到磁盘的数据。 - -## 交换属性 - -在openLooKeng节点之间为查询的不同阶段交换数据。调整这些属性可有助于解决节点间通信问题或提高网络利用率。 - -### `exchange.client-threads` - -> - **类型:** `integer` -> - **最小值:** `1` -> - **默认值:** `25` -> -> 交换客户端从其他openLooKeng节点获取数据的线程数。对于大型集群或并发量非常高的集群,设置较高的值可以提高性能,但是过高的值可能会由于上下文切换和额外的内存使用而导致性能下降。 - -### `exchange.concurrent-request-multiplier` - -> - **类型:** `integer` -> - **最小值:** `1` -> - **默认值:** `3` -> -> 确定相对于可用缓冲区内存的并发请求数的乘数。根据每个请求的平均缓冲区使用量乘以该乘数,使用可适合可用缓冲区空间的客户端数量的启发式方法来确定最大请求数。例如,如果已经使用了`exchange.max-buffer-size`为`32 MB`和`20 MB`,每个请求的平均大小为`2MB`,则客户端的最大数量为`multiplier * ((32MB - 20MB) / 2MB) = multiplier * 6`。调整此值可以调整启发式,可能会增加并发度并提高网络利用率。 - -### `exchange.max-buffer-size` - -> - **类型:** `data size` -> - **默认值:** `32MB` -> -> 交换客户端中保存处理前从其他节点取出的数据的缓冲区大小。较大的缓冲区可以提高较大集群的网络吞吐量,从而减少查询处理时间,但会减少可用于其他用途的内存量。 - -### `exchange.max-response-size` - -> - **类型:** `data size` -> - **最小值:** `1MB` -> - **默认值:** `16MB` -> -> 交换请求返回的最大响应大小。响应将被放置在交换客户机缓冲区中,该缓冲区在交换的所有并发请求之间共享。 -> -> 如果网络延迟较高,增大该值可以提高网络吞吐量。减小该值可以提高大型集群的查询性能,因为它减少了由于交换客户端缓冲区保存了较多任务(而不是保存较少任务中的较多数据)的响应而导致的倾斜。 - -### `sink.max-buffer-size` - -> - **类型:** `data size` -> - **默认值:** `32MB` -> -> 上游任务等待拉取任务数据的输出缓冲区大小。如果任务输出是经过哈希分区的,那么缓冲区将在所有分区的使用者之间共享。如果网络延迟较高或集群中有多个节点,增加此值可以提高在阶段之间传输的数据的网络吞吐量。 - -## 任务属性 - -### `task.concurrency` - -> - **类型:** `integer` -> - **限制:** 必须是2的幂。 -> - **默认值:** `16` -> -> 并行运算符(如联接和聚合)的默认本地并发度。该值应根据查询并发度和工作节点资源使用情况向上或向下调整。对于同时运行许多查询的集群来说,该值越低越好,因为所有正在运行的查询都已经利用了集群,所以增加更多的并发度将由于上下文切换和其他开销而导致速度变慢。对于一次只运行一个或较少查询的集群,该值越高越好。也可以使用`task_concurrency`会话属性在每个查询基础上指定。 - -### `task.http-response-threads` - -> - **类型:** `integer` -> - **最小值:** `1` -> - **默认值:** `100` -> -> 可以创建用于处理HTTP响应的最大线程数。线程是按需创建的,在空闲时被清理。因此,如果待处理的请求数量很少,则不会产生大量开销。在并发查询数高的集群上或在有数百或数千个工作节点的集群上,更多的线程可能会有帮助。 - -### `task.http-timeout-threads` - -> - **类型:** `integer` -> - **最小值:** `1` -> - **默认值:** `3` -> -> 生成HTTP响应时用于处理超时的线程数。如果所有线程都频繁使用,则应增大此值。这可以通过`io.prestosql.core.server:name=AsyncHttpExecutionMBean:TimeoutExecutor` JMX对象进行监视。如果`ActiveCount`始终与`PoolSize`相同,则增加线程数。 - -### `task.info-update-interval` - -> - **类型:** `duration` -> - **最小值:** `1ms` -> - **最大值:** `10s` -> - **默认值:** `3s` -> -> 控制任务信息的时效性,用于调度。较大的值可以降低协调节点CPU负载,但可能导致次优的分片调度。 - -### `task.max-partial-aggregation-memory` - -> - **类型:** `data size` -> - **默认值:** `16MB` -> -> 分布式聚合时部分聚合结果的最大大小。增大此值可以允许在刷新之前在本地保留更多的组,从而减少网络传输和CPU利用率,但要以增加内存利用率为代价。 - -### `task.max-worker-threads` - -> - **类型:** `integer` -> - **默认值:** `Node CPUs * 2` -> -> 设置工作节点用来处理分片的线程数。如果工作节点CPU利用率较低且所有线程都在使用,则增加此数量可以提高吞吐量,但会导致堆空间使用率增加。设置过高的值可能会由于上下文切换而导致性能下降。通过`io.prestosql.core.execution.executor:name=TaskExecutor.RunningSplits` JXM对象的`RunningSplits`属性可以获得活动线程的数量。 - -### `task.min-drivers` - -> - **类型:** `integer` -> - **默认值:** `task.max-worker-threads * 2` -> -> 工作节点上运行中的叶子分片的目标个数。这是一个最小值,因为每个叶任务保证至少`3`个运行分片。还保证运行非叶子任务,以防止死锁。较低的值可能提高对新任务的响应能力,但可能导致资源利用不足。较高的值可以提高资源利用率,但会占用额外的内存。 - -### `task.writer-count` - -> - **类型:** `integer` -> - **限制:** 必须是2的幂。 -> - **默认值:** `1` -> -> 每个工作节点每个查询的并发写入器线程数。增加该值可以提高写入速度,尤其在查询不是I/O绑定并且可以利用额外的CPU进行并行写入时。(某些连接器由于压缩或其他原因,在写入时可能会在CPU上出现瓶颈).设置该值过高可能导致集群因资源使用率过高而过载。也可以使用`task_writer_count`会话属性在每个查询基础上指定。 - -## 节点调度器属性 - -### `node-scheduler.max-splits-per-node` - -> - **类型:** `integer` -> - **默认值:** `100` -> -> 每个工作节点可以运行的分片总数的目标值。 -> -> 如果要批量提交查询(例如,定期运行大量报告),或者对于产生许多分片且快速完成的连接器,建议使用较高的值。增加此值可以确保工作节点有足够的分片来充分利用,从而改善查询延迟。 -> -> 设置此值过高将浪费内存,并可能导致性能降低,因为分片在工作节点之间不平衡。理想情况下,应该设置始终至少有一个分片等待处理,但不要更高。 - -### `node-scheduler.max-pending-splits-per-task` - -> - **类型:** `integer` -> - **默认值:** `10` -> -> 每个工作节点在单个查询阶段可以排队等待的未处理分片数,即使该节点已经处于总分片数的限制。每个阶段需要允许最小数量的分片以防止饥饿和死锁。 -> -> 此值必须小于`node-scheduler.max-splits-per-node`,通常由于相同的原因而增加。如果设置过高,也有类似的缺点。 - -### `node-scheduler.min-candidates` - -> - **类型:** `integer` -> - **最小值:** `1` -> - **默认值:** `10` -> -> 选择分片的目标节点时节点调度器将评估的最小候选节点数。将此值设置过低可能会使无法在所有工作节点之间适当平衡。将此值设置过高可能会增加查询延迟,并增加协调器CPU使用率。 - -### `node-scheduler.network-topology` - -> - **类型:** `string` -> - **允许值:** `legacy`,`flat` -> - **默认值:** `legacy` -> -> 设置调度分片时使用的网络拓扑。`legacy`调度分片时忽略拓扑。`flat`会尝试在数据所在的主机上调度分片,为本地分片预留50%的工作队列。对于分布式存储与openLooKeng worker运行在相同节点上的集群,推荐使用`flat`。 - -## 优化器属性 - -### `optimizer.dictionary-aggregation` - -> - **类型:** `boolean` -> - **默认值:** `false` -> -> 对字典上的聚合启用优化。也可以使用`dictionary_aggregation`会话属性在每个查询基础上指定。 - -### `optimizer.optimize-hash-generation` - -> - **类型:** `boolean` -> - **默认值:** `true` -> -> 在执行期间的早期为分布、联接和聚合计算哈希代码,允许在查询的后期在操作之间共享结果。这可以通过避免多次计算相同的哈希来降低CPU使用率,但代价是为哈希进行额外的网络传输。在大多数情况下,这将减少整个查询处理时间。也可以使用`optimize_hash_generation`会话属性在每个查询基础上指定。 -> -> 在使用[EXPLAIN](../sql/explain.md)时禁用此属性通常很有帮助,这样可以使查询计划更易读。 - -### `optimizer.optimize-metadata-queries` - -> - **类型:** `boolean` -> - **默认值:** `false` -> -> 通过使用存储为元数据的值来启用对一些聚合的优化。这允许openLooKeng在恒定的时间内执行一些简单的查询。目前,该优化适用于分区键的`max`、`min`和`approx_distinct`,以及其它对输入(包括`DISTINCT`聚集)的基数不敏感的聚集。使用此属性可以大大加快某些查询的速度。 -> -> 主要的缺点是,如果连接器为没有行的分区返回分区键,可能会产生不正确的结果。特别是,如果空分区是由其他系统创建的(openLooKeng不能创建),那么Hive连接器可以返回空分区。 - -### `optimizer.push-aggregation-through-join` - -> - **类型:** `boolean` -> - **默认值:** `true` -> -> 如果聚合位于外联接上,并且来自联接外部的所有列都在分组子句中,则聚合被推送到外联接之下。这种优化对于相关的标量子查询尤其有用,这些子查询通过外联接被重写为聚合。例如: -> -> ```sql -> SELECT * FROM item i -> WHERE i.i_current_price > ( -> SELECT AVG(j.i_current_price) FROM item j -> WHERE i.i_category = j.i_category); -> ``` -> -> 启用此优化可以减少联接需要处理的数据量,从而大大加快查询速度。 但是,此优化可能会减慢一些具有非常选择性联接的查询。也可以使用`push_aggregation_through_join`会话属性在每个查询基础上指定。 - -### `optimizer.push-table-write-through-union` - -> - **类型:** `boolean` -> - **默认值:** `true` -> -> 在写入数据的查询中使用`UNION ALL`时,对写入进行并行化。这提高了在`UNION ALL`查询中写入输出表的速度,因为这些写入在收集结果时不需要额外的同步。当写入速度尚未饱和时,启用此优化可以提高`UNION ALL`速度。但是,此优化可能会减慢负载已经很重的系统中的查询。也可以使用`push_table_write_through_union`会话属性在每个查询基础上指定。 - -### `optimizer.join-reordering-strategy` - -> - **类型:** `string` -> - **允许值:** `AUTOMATIC`,`ELIMINATE_CROSS_JOINS`,`NONE` -> - **默认值:** `ELIMINATE_CROSS_JOINS` -> -> 要使用的联接重新排序策略。 `NONE`维持查询中列出的表的顺序。 `ELIMINATE_CROSS_JOINS`重新排序联接,以尽可能消除交叉联接,否则保持原始查询顺序。当重新排序连接时,该值还尽可能地保持原来的表顺序。`AUTOMATIC`枚举可能的顺序并使用基于统计的成本估计来确定最小成本顺序。如果统计数据不可用,或者由于任何原因无法计算成本,则使用`ELIMINATE_CROSS_JOINS`策略。也可以使用`join_reordering_strategy`会话属性在每个查询基础上指定。 - -### `optimizer.max-reordered-joins` - -> - **类型:** `integer` -> - **默认值:** `9` -> -> 当optimizer.join-reordering-strategy设置为基于成本时,此属性确定可一次重新排序的最大联接数。 -> -> **警告** -> -> 可能的连接顺序数随着关系数的增大而增大,因此增加此值会导致严重的性能问题。 - -## 正则表达式函数属性 - -下列属性允许调优[正则表达式函数](../functions/regexp.md)。 - -### `regex-library` - -> - **类型:** `string` -> - **允许值:** `JONI`,`RE2J` -> - **默认值:** `JONI` -> -> 用于正则表达式函数的库。一般来说,`JONI`对于一般用途的速度要快一些,但是对于某些表达式模式可能需要指数级的时间。`RE2J`使用不同的算法保证线性时间,但通常速度较慢。 - -### `re2j.dfa-states-limit` - -> - **类型:** `integer` -> - **最小值:** `2` -> - **默认值:** `2147483647` -> -> RE2J在为正则表达式匹配构建快速但可能占用大量内存的确定性有限自动机(DFA)时所使用的最大状态数。如果达到限制,RE2J将回落到使用速度较慢但较少内存密集型非确定性有限自动机(NFA)的算法。减小此值会降低正则表达式搜索的最大内存占用,但会牺牲速度。 - -### `re2j.dfa-retries` - -> - **类型:** `integer` -> - **最小值:** `0` -> - **默认值:** `5` -> -> 在RE2J使用较慢但较少内存密集型的NFA算法对所有后续输入进行搜索前,如果DFA算法达到状态限制,RE2J将重试该算法的次数。如果遇到给定输入行的极限值可能是离群值,那么你希望能够使用更快的DFA算法来处理后续行。如果你也有可能达到匹配后续行的限制,那么你应该从头开始使用正确的算法,以避免浪费时间和资源。处理的行数越多,该值应该越大。 - -## 启发式索引属性 - -启发式索引是外部索引模块,可用于过滤连接器级别的行。 位图,Bloom和MinMaxIndex是openLooKeng提供的索引列表。 到目前为止,位图索引支持使用ORC存储格式的表支持蜂巢连接器。 - -### `hetu.heuristicindex.filter.enabled` - -> - **类型:** `boolean` -> - **默认值:** `false` -> -> 此属性启用启发式索引。还有一个会话属性`heuristicindex_filter_enabled`,可按会话设置。注意:当配置文件中将此全局属性设置为`true`时,会话属性仅用于临时打开和关闭索引筛选。当未全局启用索引筛选器时,无法使用该会话属性来打开。 - -### `hetu.heuristicindex.filter.cache.max-memory` - -> - **类型:** `data size` -> - **默认值:** `10GB` -> -> 由于索引文件很少被改动,将索引缓存可以提升性能,减少从文件系统读取索引所需时间。这一属性控制索引缓存允许使用的内存大小,当缓存已满,最旧的缓存将被移除,由新的缓存替代(LRU缓存)。 - -### `hetu.heuristicindex.filter.cache.soft-reference` - -> - **类型:** `boolean` -> - **默认值:** `true` -> -> 缓存索引可以提供更好的性能,但是需要使用一部分内存空间。启用这一属性将允许垃圾回收器(GC)在内存不足时从缓存中清除内容来释放内存。 -> -> 注意:这一特性还在实验中,请谨慎使用! - -### `hetu.heuristicindex.filter.cache.ttl` - -> - 类型:`Duration` -> - **默认值:** `24h` -> -> 索引缓存的有效时间。 - -### `hetu.heuristicindex.filter.cache.loading-threads` - -> - 类型:`integer` -> - **默认值:** `10` -> -> 从索引存储文件系统并行加载索引时使用的线程数量。 - -### `hetu.heuristicindex.filter.cache.loading-delay` - -> - 类型:`Duration` -> - **默认值:** `10s` -> -> 在异步加载索引到缓存前等待的时长。 - -### `hetu.heuristicindex.indexstore.uri` - -> - 类型:`string` -> - **默认值:** `/opt/hetu/indices/` -> -> 所有索引文件存储在的目录。 每个索引将存储在其自己的子目录中。 - -### `hetu.heuristicindex.indexstore.filesystem.profile` - -> - **类型** `string` -> -> 此属性定义用于存储索引文件的文件系统属性描述文件名称,该名称对应的属性文件应该存在于`etc/filesystem/`中。 - -## 执行计划缓存属性 - -执行计划缓存功能允许协调器在相同的查询之间重用执行计划, 构建另一个执行计划的过程,从而减少了所需的查询预处理量。 - -### `hetu.executionplan.cache.enabled` - -> - **类型:** `boolean` -> - **默认值:** `false` -> -> 启用或禁用执行计划缓存。 默认禁用。 - -### `hetu.executionplan.cache.limit` - -> - **类型:** `integer` -> - **默认值:** `10000` -> -> 保留在缓存中的最大执行计划数 - -### `hetu.executionplan.cache.timeout` - -> - **类型:** `integer` -> - **默认值:** `86400000 ms` -> -> 上次访问后使缓存的执行计划失效的时间(以毫秒为单位) - -## SplitCacheMap属性 - -必须启用SplitCacheMap以支持缓存行数据。 启用后,协调器将存储表,分区和分片调度元数据 帮助进行缓存亲和力调度。 - -### `hetu.split-cache-map.enabled` - -> - **类型:**`boolean` -> - **默认值:** `false` -> -> 此属性启用分片缓存功能。 如果启用了状态存储,则分片缓存映射配置也会自动复制到状态存储中。 在具有多个协调器的HA设置的情况下,状态存储用于在协调器之间共享分片的缓存映射。 - -### `hetu.split-cache-map.state-update-interval` - -> - **类型:** `integer` -> - **默认值:** `2 seconds` -> -> 此属性控制在状态存储中更新分割缓存映射的频率。 它主要适用于HA部署。 - -## 自动清空 - -> 自动清空使系统能够通过持续监测需要清空的表来自动管理清空作业,以保持最佳性能。引擎从符合清空条件的数据源获取表,并触发对这些表的清空操作。 - -### `auto-vacuum.enabled:` - -> - **类型:** `boolean` -> - **默认值:** `false` -> -> 此属性用于启用自动清空功能。 -> -> **注意:** 此属性只能在协调节点中配置。 - -### `auto-vacuum.scan.interval` - -> - **类型:** `Duration` -> - **默认值:** `10m` -> -> 此属性为从数据源获取情况表信息并触发对这些表的清空操作的定时间隔。计时器在服务器启动时开始,并将在配置的间隔内保持调度。最小值为15s,最大值为24h。 -> -> **注意:** 此属性只能在协调节点中配置。 - -### `auto-vacuum.scan.threads` - -> - **类型:** `integer` -> - **默认值:** `3` -> -> 用于自动清空功能的线程数。最小值为1,最大值为16。 -> -> **注意:** 此属性只能在协调节点中配置。 +# 属性参考 + +本节将介绍最重要的配置属性,这些属性可用于调优openLooKeng或在需要时更改其行为。 + +## 通用属性 + +### `join-distribution-type` + +> - **类型:** `string` +> - **允许值:** `AUTOMATIC`,`PARTITIONED`,`BROADCAST` +> - **默认值:** `PARTITIONED` +> +> 要使用的分布式联接的类型。 设置为`PARTITIONED`时,openLooKeng将使用哈希分布式联接。 当设置为`BROADCAST`时,将向集群中所有从左表获得数据的节点广播右表。分区联接要求使用联接键的哈希重分布这两个表。这可能比广播联接慢(有时极慢),但允许更大的联接。特别是如果右表比左表小得多,则广播联接将更快。 但是广播联接要求联接右侧过滤后的表适合每个节点的内存,而分布式联接只需要适合所有节点的分布式内存。当设置为`AUTOMATIC`时,openLooKeng将基于成本决定哪种分布类型是最优的。还将考虑将左右输入切换到联接。 在`AUTOMATIC`模式中,如果无法计算成本,例如表没有统计信息,openLooKeng将默认哈希分布式联接。也可以使用`join_distribution_type`会话属性在每个查询基础上指定。 + +### `redistribute-writes` + +> - **类型:** `boolean` +> - **默认值:** `true` +> +> 此属性允许在写入数据之前重新分布数据。这可以通过在集群中的节点间散列数据来消除数据倾斜带来的性能影响。当已知输出数据集没有发生倾斜时,可以停用数据分布,以避免在网络上散列和重分布所有数据的开销。也可以使用`redistribute_writes`会话属性在每个查询基础上指定。 + +### `stack-trace-visible` + +> - **类型:** `boolean` +> - **允许值:** `true`, `false` +> - **默认值:** `false` +> +> 此属性控制系统是否能够在CLI、WEB UI等对外展示系统出现Exception时的代码调用栈. 当设置为`true`时对外展示给所有用户,设置为`false`或者采用默认设置,不展示给任何用户。 + +## http 安全头部属性 + +### `http-header.content-security-policy` + +> - **类型:** `string` +> - **默认值:** `object-src 'none'` +> +> 此属性设置 `content-security-policy` 设置相关值。 + +### `http-header.referrer-policy` + +> - **类型:** `string` +> - **默认值:** `strict-origin-when-cross-origin` +> +> 此属性设置 `referrer-policy` 设置相关值。 + +### `http-header.x-content-type-options` + +> - **类型:** `string` +> - **默认值:** `nosniff` +> +> 此属性设置 `content-security-policy` 设置相关值。 + +### `http-header.x-frame-options` + +> - **类型:** `string` +> - **默认值:** `deny` +> +> 此属性设置 `content-security-policy` 设置相关值。 + +### `http-header.x-permitted-cross-domain-policies` + +> - **类型:** `string` +> - **默认值:** `master-only` +> +> 此属性设置 `x-permitted-cross-domain-policies` 设置相关值。 + +### `http-header.x-xss-protection` + +> - **类型:** `string` +> - **默认值:** `1; mode=block` +> +> 此属性设置 `http-header.x-xss-protection` 设置相关值。 + +## 内存管理属性 + +### `query.max-memory-per-node` + +> - **类型:** `data size` +> - **默认值:** `JVM max memory * 0.1` +> +> 此属性是查询在工作节点上可以使用的最大用户内存量。用户内存是在执行期间为用户查询直接归属或可控制的事物分配的。例如,在执行期间构建的哈希表使用的内存、排序期间使用的内存等。当任何工作节点上的查询的用户内存分配达到此限制时,该工作节点将被杀死。 + +### `query.max-total-memory-per-node` + +> - **类型:** `data size` +> - **默认值:** `JVM max memory * 0.3` +> +> 此属性是查询在工作节点上可以使用的最大用户和系统内存量。系统内存是在执行期间为用户查询无法直接归属或可控制的事物分配的。例如,由读取器、写入器、网络缓冲区等分配的内存。当任何工作节点上的查询所分配的用户和系统内存的总和达到此限制时,该工作节点将被杀死。`query.max-total-memory-per-node`的值必须大于`query.max-memory-per-node`。 + +### `query.max-memory` + +> - **类型:** `data size` +> - **默认值:** `20GB` +> +> 此属性是查询在整个集群上可以使用的最大用户内存量。用户内存是在执行期间为用户查询直接归属或可控制的事物分配的。例如,在执行期间构建的哈希表使用的内存、排序期间使用的内存等。当一个跨所有工作节点的查询的用户内存分配达到此限制时,该工作节点将被杀死。 + +### `query.max-total-memory` + +> - **类型:** `data size` +> - **默认值:** `query.max-memory * 2` +> +> 此属性是查询在整个集群上可以使用的最大用户和系统内存量。系统内存是在执行期间为用户查询无法直接归属或可控制的事物分配的。例如,由读取器、写入器、网络缓冲区等分配的内存。当一个跨所有工作节点的查询所分配的用户和系统内存的总和达到此限制时,该工作节点将被杀死。`query.max-total-memory`的值必须大于`query.max-memory`。 + +### `memory.heap-headroom-per-node` + +> - **类型:** `data size` +> - **默认值:** `JVM max memory * 0.3` +> +> 此属性是在JVM堆中为openLooKeng不跟踪的分配留作裕量/缓冲区的内存量。 + +## 溢出属性 + +### `experimental.spill-enabled` + +> - **类型:** `boolean` +> - **默认值:** `false` +> +> 尝试将内存溢出到磁盘,以避免超出查询的内存限制。 +> +> 溢出是将内存卸载到磁盘。此过程允许内存占用大的查询,代价是执行时间变慢。聚合、联接(内联接和外联接)、排序和窗口函数支持溢出。此属性不会减少其他联接类型所需的内存使用。 +> +> 注意,这是一个实验特性,应谨慎使用。 +> +> 此配置属性可由`spill_enabled`会话属性重写。 + +### `experimental.spill-order-by` + +> - **类型:** `boolean` +> - **默认值:** `true` +> +> 尝试将内存溢出到磁盘,以避免在运行排序运算符时超出查询的内存限制。此属性必须与`experimental.spill-enabled`属性一起使用。 +> +> 此配置属性可由`spill_order_by`会话属性重写。 + +### `experimental.spill-window-operator` + +> - **类型:** `boolean` +> - **默认值:** `true` +> +> 尝试将内存溢出到磁盘,以避免在运行窗口运算符时超出查询的内存限制。此属性必须与`experimental.spill-enabled`属性一起使用。 +> +> 此配置属性可由`spill_window_operator`会话属性重写。 + +### `experimental.spiller-spill-path` + +> - **类型:** `string` +> - **无默认值。** 启用溢出时必须设置。 +> +> 溢出内容写入的目录。该属性可以是一个逗号分隔的列表,以同时溢出到多个目录,这有助于利用系统中安装的多个驱动器。 +> +> 不建议溢出到系统驱动器上。最重要的是,不要溢出到写入JVM日志的驱动器,因为磁盘过度使用可能导致JVM长时间暂停,从而导致查询失败。 + +### `experimental.spiller-max-used-space-threshold` + +> - **类型:** `double` +> - **默认值:** `0.9` +> +> 如果指定溢出路径的磁盘空间使用率高于此阈值,则该溢出路径将不适用于溢出。 + +### `experimental.spiller-threads` + +> - **类型:** `integer` +> - **默认值:** `4` +> +> 溢出线程数。如果默认值不能使底层溢出设备饱和(例如,在使用RAID时),增大该值。 + +### `experimental.max-spill-per-node` + +> - **类型:** `data size` +> - **默认值:** `100 GB` +> +> 单个节点上所有查询使用的最大溢出空间。 + +### `experimental.query-max-spill-per-node` + +> - **类型:** `data size` +> - **默认值:** `100 GB` +> +> 单个查询在单个节点上使用的最大溢出空间。 + +### `experimental.aggregation-operator-unspill-memory-limit` + +> - **类型:** `data size` +> - **默认值:** `4 MB` +> +> 取消溢出单个聚合运算符实例所使用的内存限制。 + +### `experimental.spill-compression-enabled` + +> - **类型:** `boolean` +> - **默认值:** `false` +> +> 为溢出到磁盘的页面启用数据压缩。 + +### `experimental.spill-encryption-enabled` + +> - **类型:** `boolean` +> - **默认值:** `false` +> +> 允许使用随机生成的密钥(每个溢出文件)来加密和解密溢出到磁盘的数据。 + +## 交换属性 + +在openLooKeng节点之间为查询的不同阶段交换数据。调整这些属性可有助于解决节点间通信问题或提高网络利用率。 + +### `exchange.client-threads` + +> - **类型:** `integer` +> - **最小值:** `1` +> - **默认值:** `25` +> +> 交换客户端从其他openLooKeng节点获取数据的线程数。对于大型集群或并发量非常高的集群,设置较高的值可以提高性能,但是过高的值可能会由于上下文切换和额外的内存使用而导致性能下降。 + +### `exchange.concurrent-request-multiplier` + +> - **类型:** `integer` +> - **最小值:** `1` +> - **默认值:** `3` +> +> 确定相对于可用缓冲区内存的并发请求数的乘数。根据每个请求的平均缓冲区使用量乘以该乘数,使用可适合可用缓冲区空间的客户端数量的启发式方法来确定最大请求数。例如,如果已经使用了`exchange.max-buffer-size`为`32 MB`和`20 MB`,每个请求的平均大小为`2MB`,则客户端的最大数量为`multiplier * ((32MB - 20MB) / 2MB) = multiplier * 6`。调整此值可以调整启发式,可能会增加并发度并提高网络利用率。 + +### `exchange.max-buffer-size` + +> - **类型:** `data size` +> - **默认值:** `32MB` +> +> 交换客户端中保存处理前从其他节点取出的数据的缓冲区大小。较大的缓冲区可以提高较大集群的网络吞吐量,从而减少查询处理时间,但会减少可用于其他用途的内存量。 + +### `exchange.max-response-size` + +> - **类型:** `data size` +> - **最小值:** `1MB` +> - **默认值:** `16MB` +> +> 交换请求返回的最大响应大小。响应将被放置在交换客户机缓冲区中,该缓冲区在交换的所有并发请求之间共享。 +> +> 如果网络延迟较高,增大该值可以提高网络吞吐量。减小该值可以提高大型集群的查询性能,因为它减少了由于交换客户端缓冲区保存了较多任务(而不是保存较少任务中的较多数据)的响应而导致的倾斜。 + +### `sink.max-buffer-size` + +> - **类型:** `data size` +> - **默认值:** `32MB` +> +> 上游任务等待拉取任务数据的输出缓冲区大小。如果任务输出是经过哈希分区的,那么缓冲区将在所有分区的使用者之间共享。如果网络延迟较高或集群中有多个节点,增加此值可以提高在阶段之间传输的数据的网络吞吐量。 + +## 任务属性 + +### `task.concurrency` + +> - **类型:** `integer` +> - **限制:** 必须是2的幂。 +> - **默认值:** `16` +> +> 并行运算符(如联接和聚合)的默认本地并发度。该值应根据查询并发度和工作节点资源使用情况向上或向下调整。对于同时运行许多查询的集群来说,该值越低越好,因为所有正在运行的查询都已经利用了集群,所以增加更多的并发度将由于上下文切换和其他开销而导致速度变慢。对于一次只运行一个或较少查询的集群,该值越高越好。也可以使用`task_concurrency`会话属性在每个查询基础上指定。 + +### `task.http-response-threads` + +> - **类型:** `integer` +> - **最小值:** `1` +> - **默认值:** `100` +> +> 可以创建用于处理HTTP响应的最大线程数。线程是按需创建的,在空闲时被清理。因此,如果待处理的请求数量很少,则不会产生大量开销。在并发查询数高的集群上或在有数百或数千个工作节点的集群上,更多的线程可能会有帮助。 + +### `task.http-timeout-threads` + +> - **类型:** `integer` +> - **最小值:** `1` +> - **默认值:** `3` +> +> 生成HTTP响应时用于处理超时的线程数。如果所有线程都频繁使用,则应增大此值。这可以通过`io.prestosql.core.server:name=AsyncHttpExecutionMBean:TimeoutExecutor` JMX对象进行监视。如果`ActiveCount`始终与`PoolSize`相同,则增加线程数。 + +### `task.info-update-interval` + +> - **类型:** `duration` +> - **最小值:** `1ms` +> - **最大值:** `10s` +> - **默认值:** `3s` +> +> 控制任务信息的时效性,用于调度。较大的值可以降低协调节点CPU负载,但可能导致次优的分片调度。 + +### `task.max-partial-aggregation-memory` + +> - **类型:** `data size` +> - **默认值:** `16MB` +> +> 分布式聚合时部分聚合结果的最大大小。增大此值可以允许在刷新之前在本地保留更多的组,从而减少网络传输和CPU利用率,但要以增加内存利用率为代价。 + +### `task.max-worker-threads` + +> - **类型:** `integer` +> - **默认值:** `Node CPUs * 2` +> +> 设置工作节点用来处理分片的线程数。如果工作节点CPU利用率较低且所有线程都在使用,则增加此数量可以提高吞吐量,但会导致堆空间使用率增加。设置过高的值可能会由于上下文切换而导致性能下降。通过`io.prestosql.core.execution.executor:name=TaskExecutor.RunningSplits` JXM对象的`RunningSplits`属性可以获得活动线程的数量。 + +### `task.min-drivers` + +> - **类型:** `integer` +> - **默认值:** `task.max-worker-threads * 2` +> +> 工作节点上运行中的叶子分片的目标个数。这是一个最小值,因为每个叶任务保证至少`3`个运行分片。还保证运行非叶子任务,以防止死锁。较低的值可能提高对新任务的响应能力,但可能导致资源利用不足。较高的值可以提高资源利用率,但会占用额外的内存。 + +### `task.writer-count` + +> - **类型:** `integer` +> - **限制:** 必须是2的幂。 +> - **默认值:** `1` +> +> 每个工作节点每个查询的并发写入器线程数。增加该值可以提高写入速度,尤其在查询不是I/O绑定并且可以利用额外的CPU进行并行写入时。(某些连接器由于压缩或其他原因,在写入时可能会在CPU上出现瓶颈).设置该值过高可能导致集群因资源使用率过高而过载。也可以使用`task_writer_count`会话属性在每个查询基础上指定。 + +## 节点调度器属性 + +### `node-scheduler.max-splits-per-node` + +> - **类型:** `integer` +> - **默认值:** `100` +> +> 每个工作节点可以运行的分片总数的目标值。 +> +> 如果要批量提交查询(例如,定期运行大量报告),或者对于产生许多分片且快速完成的连接器,建议使用较高的值。增加此值可以确保工作节点有足够的分片来充分利用,从而改善查询延迟。 +> +> 设置此值过高将浪费内存,并可能导致性能降低,因为分片在工作节点之间不平衡。理想情况下,应该设置始终至少有一个分片等待处理,但不要更高。 + +### `node-scheduler.max-pending-splits-per-task` + +> - **类型:** `integer` +> - **默认值:** `10` +> +> 每个工作节点在单个查询阶段可以排队等待的未处理分片数,即使该节点已经处于总分片数的限制。每个阶段需要允许最小数量的分片以防止饥饿和死锁。 +> +> 此值必须小于`node-scheduler.max-splits-per-node`,通常由于相同的原因而增加。如果设置过高,也有类似的缺点。 + +### `node-scheduler.min-candidates` + +> - **类型:** `integer` +> - **最小值:** `1` +> - **默认值:** `10` +> +> 选择分片的目标节点时节点调度器将评估的最小候选节点数。将此值设置过低可能会使无法在所有工作节点之间适当平衡。将此值设置过高可能会增加查询延迟,并增加协调器CPU使用率。 + +### `node-scheduler.network-topology` + +> - **类型:** `string` +> - **允许值:** `legacy`,`flat` +> - **默认值:** `legacy` +> +> 设置调度分片时使用的网络拓扑。`legacy`调度分片时忽略拓扑。`flat`会尝试在数据所在的主机上调度分片,为本地分片预留50%的工作队列。对于分布式存储与openLooKeng worker运行在相同节点上的集群,推荐使用`flat`。 + +## 优化器属性 + +### `optimizer.dictionary-aggregation` + +> - **类型:** `boolean` +> - **默认值:** `false` +> +> 对字典上的聚合启用优化。也可以使用`dictionary_aggregation`会话属性在每个查询基础上指定。 + +### `optimizer.optimize-hash-generation` + +> - **类型:** `boolean` +> - **默认值:** `true` +> +> 在执行期间的早期为分布、联接和聚合计算哈希代码,允许在查询的后期在操作之间共享结果。这可以通过避免多次计算相同的哈希来降低CPU使用率,但代价是为哈希进行额外的网络传输。在大多数情况下,这将减少整个查询处理时间。也可以使用`optimize_hash_generation`会话属性在每个查询基础上指定。 +> +> 在使用[EXPLAIN](../sql/explain.md)时禁用此属性通常很有帮助,这样可以使查询计划更易读。 + +### `optimizer.optimize-metadata-queries` + +> - **类型:** `boolean` +> - **默认值:** `false` +> +> 通过使用存储为元数据的值来启用对一些聚合的优化。这允许openLooKeng在恒定的时间内执行一些简单的查询。目前,该优化适用于分区键的`max`、`min`和`approx_distinct`,以及其它对输入(包括`DISTINCT`聚集)的基数不敏感的聚集。使用此属性可以大大加快某些查询的速度。 +> +> 主要的缺点是,如果连接器为没有行的分区返回分区键,可能会产生不正确的结果。特别是,如果空分区是由其他系统创建的(openLooKeng不能创建),那么Hive连接器可以返回空分区。 + +### `optimizer.push-aggregation-through-join` + +> - **类型:** `boolean` +> - **默认值:** `true` +> +> 如果聚合位于外联接上,并且来自联接外部的所有列都在分组子句中,则聚合被推送到外联接之下。这种优化对于相关的标量子查询尤其有用,这些子查询通过外联接被重写为聚合。例如: +> +> ```sql +> SELECT * FROM item i +> WHERE i.i_current_price > ( +> SELECT AVG(j.i_current_price) FROM item j +> WHERE i.i_category = j.i_category); +> ``` +> +> 启用此优化可以减少联接需要处理的数据量,从而大大加快查询速度。 但是,此优化可能会减慢一些具有非常选择性联接的查询。也可以使用`push_aggregation_through_join`会话属性在每个查询基础上指定。 + +### `optimizer.push-table-write-through-union` + +> - **类型:** `boolean` +> - **默认值:** `true` +> +> 在写入数据的查询中使用`UNION ALL`时,对写入进行并行化。这提高了在`UNION ALL`查询中写入输出表的速度,因为这些写入在收集结果时不需要额外的同步。当写入速度尚未饱和时,启用此优化可以提高`UNION ALL`速度。但是,此优化可能会减慢负载已经很重的系统中的查询。也可以使用`push_table_write_through_union`会话属性在每个查询基础上指定。 + +### `optimizer.join-reordering-strategy` + +> - **类型:** `string` +> - **允许值:** `AUTOMATIC`,`ELIMINATE_CROSS_JOINS`,`NONE` +> - **默认值:** `ELIMINATE_CROSS_JOINS` +> +> 要使用的联接重新排序策略。 `NONE`维持查询中列出的表的顺序。 `ELIMINATE_CROSS_JOINS`重新排序联接,以尽可能消除交叉联接,否则保持原始查询顺序。当重新排序连接时,该值还尽可能地保持原来的表顺序。`AUTOMATIC`枚举可能的顺序并使用基于统计的成本估计来确定最小成本顺序。如果统计数据不可用,或者由于任何原因无法计算成本,则使用`ELIMINATE_CROSS_JOINS`策略。也可以使用`join_reordering_strategy`会话属性在每个查询基础上指定。 + +### `optimizer.max-reordered-joins` + +> - **类型:** `integer` +> - **默认值:** `9` +> +> 当optimizer.join-reordering-strategy设置为基于成本时,此属性确定可一次重新排序的最大联接数。 +> +> **警告** +> +> 可能的连接顺序数随着关系数的增大而增大,因此增加此值会导致严重的性能问题。 + +## 正则表达式函数属性 + +下列属性允许调优[正则表达式函数](../functions/regexp.md)。 + +### `regex-library` + +> - **类型:** `string` +> - **允许值:** `JONI`,`RE2J` +> - **默认值:** `JONI` +> +> 用于正则表达式函数的库。一般来说,`JONI`对于一般用途的速度要快一些,但是对于某些表达式模式可能需要指数级的时间。`RE2J`使用不同的算法保证线性时间,但通常速度较慢。 + +### `re2j.dfa-states-limit` + +> - **类型:** `integer` +> - **最小值:** `2` +> - **默认值:** `2147483647` +> +> RE2J在为正则表达式匹配构建快速但可能占用大量内存的确定性有限自动机(DFA)时所使用的最大状态数。如果达到限制,RE2J将回落到使用速度较慢但较少内存密集型非确定性有限自动机(NFA)的算法。减小此值会降低正则表达式搜索的最大内存占用,但会牺牲速度。 + +### `re2j.dfa-retries` + +> - **类型:** `integer` +> - **最小值:** `0` +> - **默认值:** `5` +> +> 在RE2J使用较慢但较少内存密集型的NFA算法对所有后续输入进行搜索前,如果DFA算法达到状态限制,RE2J将重试该算法的次数。如果遇到给定输入行的极限值可能是离群值,那么你希望能够使用更快的DFA算法来处理后续行。如果你也有可能达到匹配后续行的限制,那么你应该从头开始使用正确的算法,以避免浪费时间和资源。处理的行数越多,该值应该越大。 + +## 启发式索引属性 + +启发式索引是外部索引模块,可用于过滤连接器级别的行。 位图,Bloom和MinMaxIndex是openLooKeng提供的索引列表。 到目前为止,位图索引支持使用ORC存储格式的表支持蜂巢连接器。 + +### `hetu.heuristicindex.filter.enabled` + +> - **类型:** `boolean` +> - **默认值:** `false` +> +> 此属性启用启发式索引。还有一个会话属性`heuristicindex_filter_enabled`,可按会话设置。注意:当配置文件中将此全局属性设置为`true`时,会话属性仅用于临时打开和关闭索引筛选。当未全局启用索引筛选器时,无法使用该会话属性来打开。 + +### `hetu.heuristicindex.filter.cache.max-memory` + +> - **类型:** `data size` +> - **默认值:** `10GB` +> +> 由于索引文件很少被改动,将索引缓存可以提升性能,减少从文件系统读取索引所需时间。这一属性控制索引缓存允许使用的内存大小,当缓存已满,最旧的缓存将被移除,由新的缓存替代(LRU缓存)。 + +### `hetu.heuristicindex.filter.cache.soft-reference` + +> - **类型:** `boolean` +> - **默认值:** `true` +> +> 缓存索引可以提供更好的性能,但是需要使用一部分内存空间。启用这一属性将允许垃圾回收器(GC)在内存不足时从缓存中清除内容来释放内存。 +> +> 注意:这一特性还在实验中,请谨慎使用! + +### `hetu.heuristicindex.filter.cache.ttl` + +> - 类型:`Duration` +> - **默认值:** `24h` +> +> 索引缓存的有效时间。 + +### `hetu.heuristicindex.filter.cache.loading-threads` + +> - 类型:`integer` +> - **默认值:** `10` +> +> 从索引存储文件系统并行加载索引时使用的线程数量。 + +### `hetu.heuristicindex.filter.cache.loading-delay` + +> - 类型:`Duration` +> - **默认值:** `10s` +> +> 在异步加载索引到缓存前等待的时长。 + +### `hetu.heuristicindex.indexstore.uri` + +> - 类型:`string` +> - **默认值:** `/opt/hetu/indices/` +> +> 所有索引文件存储在的目录。 每个索引将存储在其自己的子目录中。 + +### `hetu.heuristicindex.indexstore.filesystem.profile` + +> - **类型** `string` +> +> 此属性定义用于存储索引文件的文件系统属性描述文件名称,该名称对应的属性文件应该存在于`etc/filesystem/`中。 +> +> - `LOCAL` 本地文件系统只应该被用于本地测试,或单节点部署情形。(否则索引文件将无法在机器之间共享) +> - `HDFS` 应用于生产环境来在集群中共享数据。 + +## 执行计划缓存属性 + +执行计划缓存功能允许协调器在相同的查询之间重用执行计划, 构建另一个执行计划的过程,从而减少了所需的查询预处理量。 + +### `hetu.executionplan.cache.enabled` + +> - **类型:** `boolean` +> - **默认值:** `false` +> +> 启用或禁用执行计划缓存。 默认禁用。 + +### `hetu.executionplan.cache.limit` + +> - **类型:** `integer` +> - **默认值:** `10000` +> +> 保留在缓存中的最大执行计划数 + +### `hetu.executionplan.cache.timeout` + +> - **类型:** `integer` +> - **默认值:** `86400000 ms` +> +> 上次访问后使缓存的执行计划失效的时间(以毫秒为单位) + +## SplitCacheMap属性 + +必须启用SplitCacheMap以支持缓存行数据。 启用后,协调器将存储表,分区和分片调度元数据 帮助进行缓存亲和力调度。 + +### `hetu.split-cache-map.enabled` + +> - **类型:**`boolean` +> - **默认值:** `false` +> +> 此属性启用分片缓存功能。 如果启用了状态存储,则分片缓存映射配置也会自动复制到状态存储中。 在具有多个协调器的HA设置的情况下,状态存储用于在协调器之间共享分片的缓存映射。 + +### `hetu.split-cache-map.state-update-interval` + +> - **类型:** `integer` +> - **默认值:** `2 seconds` +> +> 此属性控制在状态存储中更新分割缓存映射的频率。 它主要适用于HA部署。 + +## 自动清空 + +> 自动清空使系统能够通过持续监测需要清空的表来自动管理清空作业,以保持最佳性能。引擎从符合清空条件的数据源获取表,并触发对这些表的清空操作。 + +### `auto-vacuum.enabled:` + +> - **类型:** `boolean` +> - **默认值:** `false` +> +> 此属性用于启用自动清空功能。 +> +> **注意:** 此属性只能在协调节点中配置。 + +### `auto-vacuum.scan.interval` + +> - **类型:** `Duration` +> - **默认值:** `10m` +> +> 此属性为从数据源获取情况表信息并触发对这些表的清空操作的定时间隔。计时器在服务器启动时开始,并将在配置的间隔内保持调度。最小值为15s,最大值为24h。 +> +> **注意:** 此属性只能在协调节点中配置。 + +### `auto-vacuum.scan.threads` + +> - **类型:** `integer` +> - **默认值:** `3` +> +> 用于自动清空功能的线程数。最小值为1,最大值为16。 +> +> **注意:** 此属性只能在协调节点中配置。 diff --git a/hetu-docs/zh/images/index-decision.png b/hetu-docs/zh/images/index-decision.png new file mode 100644 index 000000000..b89d36f58 Binary files /dev/null and b/hetu-docs/zh/images/index-decision.png differ diff --git a/hetu-docs/zh/indexer/bitmap.md b/hetu-docs/zh/indexer/bitmap.md index 8e0ddcc7b..f625342b6 100644 --- a/hetu-docs/zh/indexer/bitmap.md +++ b/hetu-docs/zh/indexer/bitmap.md @@ -1,19 +1,37 @@ -# 位图索引 +# BitMap(位图)索引 +BitMap索引使用位图。索引的大小随着索引列中不同值的个数而增加。例如,一个标记性别的列很小,而一个ID列的索引则会极大(不推荐)。 + +注意:在ORC算子下推启用时,BitMap索引效果更好。可以通过设置`hive.properties`中的`hive.orc-predicate-pushdown-enabled=true`来启用, +或者在命令行中启用`set session hive.orc_predicate_pushdown_enabled=true;`。 + +参见[Properties](../admin/properties.md)获得更多信息。 + +## 过滤 + +1. BitMap索引用于过滤从ORC文件中读取的数据,且仅供worker节点使用。 + +## 选择适用的列 + +BitMap索引在拥有较少不同值数量的列上比较适用,例如:性别。 + +## 支持的运算符 + + = Equality + ## 用例 -位图索引用于过滤从ORC文件中读取的数据,且仅供**worker**节点使用。 - -- 如果包含这个索引的列是查询中谓词的一部分,那么读取ORC文件的性能可能会得提升。 - -例如,如果索引在`country`列,并且查询语句是 - -``` sql -select * from table where country="China" +创建: +```sql +create index idx using bitmap on hive.hindex.users (gender); +create index idx using bitmap on hive.hindex.users (gender) where regionkey=1; +create index idx using bitmap on hive.hindex.users (gender) where regionkey in (3, 1); ``` -- 如果列的值不是太明显(例如国家)和分散,则此索引最有效。 - -例如,假设表存储的是用户来自何处的信息,并且表数据存在于10个文件中。可能有多个用户来自某一国家,因此每个文件将有一些来自该国的用户。如果我们在国家列创建一个位图索引,那么在读取数据文件时,我们可以在早期执行过滤。即,谓词被下推到文件读取。如果没有这个索引,所有的数据文件将会作为页读入内存,然后再过滤。如果有此索引,我们可以确保内存页中已经只包含与谓词匹配的行。这有助于减少内存和CPU使用率,并且提高多并发查询的性能。 +* 假设表已按照`regionkey`列分区 +使用: +```sql +select name from hive.hindex.users where gender="female" +``` \ No newline at end of file diff --git a/hetu-docs/zh/indexer/bloom.md b/hetu-docs/zh/indexer/bloom.md index d9e3fc5eb..d6e9ec1b2 100644 --- a/hetu-docs/zh/indexer/bloom.md +++ b/hetu-docs/zh/indexer/bloom.md @@ -1,20 +1,45 @@ # Bloom索引 +Bloom索引实用布隆过滤器来过滤数据。索引体积非常小。 + +## 过滤 + +1. Bloom索引用于调度时的分片过滤,被coordinator节点使用。 +2. Bloom索引也用于worker节点上,用于在读取ORC文件是过滤stripes。 + +## 选择适用的列 + +位图索引在拥有较多不同值数量的列上比较适用,例如:ID。 + +## 支持的运算符 + + = Equality + +## 配置参数 + +### `bloom.fpp` + +> - **类型:** `Double` +> - **默认值:** `0.001` +> +> 改变布隆过滤器的FPP (false positive probability)。 +> 更小的FPP会提高索引的过滤能力,但是会增加索引的体积。在大多数情况下默认值就足以够用。 +> 如果创建的索引太大,可以考虑增加这个值(例如,至0.05)。 + ## 用例 -Bloom索引用于分片过滤,且仅被**coordinator**节点使用。 - -- 如果查询中作为谓词一部分的列存在此索引,openLooKeng可以通过筛选预定Splits来提高查询性能。 - -例如,如果列`id`包含此索引,并且查询语句如下: - +创建索引: ```sql -select * from table where id=12345 +create index idx using bloom on hive.hindex.users (id); +create index idx using bloom on hive.hindex.users (id) where regionkey=1; +create index idx using bloom on hive.hindex.users (id) where regionkey in (3, 1); +create index idx using bloom on hive.hindex.users (id) WITH ("bloom.fpp" = '0.001'); ``` -- 如果列的值是唯一的(例如userid)并且不太分散,则Bloom索引最有效。 +* 假设表已按照`regionkey`列分区 -例如,假设表中存储了用户信息,且表数据存在于10个文件中。 对于给定的用户ID,只有一个文件包含该数据。因此,对用户ID创建索引将帮助我们在调度时间内过滤掉10个文件中的9个文件,并节省大量用于读取每个文件的IO时间。 - -*提示:如果可能,建议对索引列中的数据进行排序*。 +使用: +```sql +select name from hive.hindex.users where id=123 +``` \ No newline at end of file diff --git a/hetu-docs/zh/indexer/btree.md b/hetu-docs/zh/indexer/btree.md new file mode 100644 index 000000000..87fb1d57d --- /dev/null +++ b/hetu-docs/zh/indexer/btree.md @@ -0,0 +1,48 @@ +# BTree索引 + +BTree索引使用二叉树数据结构存储。索引的大小随着索引列中不同值的个数而增加。 + +## 过滤 + +1. Bloom索引用于调度时的分片过滤,被coordinator节点使用。 + +## 选择适用的列 + +位图索引在拥有较多不同值数量的列上比较适用,例如:ID。除此之外,BTree索引还要求表是分区的。 + +在BTree和Bloom索引之间选择时,需要考虑: +- Bloom索引只支持`=` +- Btree索引要求表是分区的 +- Bloom索引是不确定的,而BTree索引是确定的。因此BTree通常有更好的过滤性能 +- BTree索引比Bloom索引更大 + +## 支持的运算符 + + = Equality + > Greater than + >= Greater than or equal + < Less than + <= Less than or equal + BETWEEN Between range + IN IN set + +## 用例 + +创建索引: +```sql +create index idx using btree on hive.hindex.orders (orderid) with (level=partition) where orderDate='01-10-2020' ; +create index idx using btree on hive.hindex.orders (orderid) with (level=partition) where orderDate in ('01-10-2020', '01-10-2020'); +``` + +* 假设表已按照`orderDate`列分区 + +使用索引: +```sql +select * from hive.hindex.orders where orderid=12345 +select * from hive.hindex.orders where orderid>12345 +select * from hive.hindex.orders where orderid<12345 +select * from hive.hindex.orders where orderid>=12345 +select * from hive.hindex.orders where orderid<=12345 +select * from hive.hindex.orders where orderid between (10000, 20000) +select * from hive.hindex.orders where orderid in (12345, 7890) +``` \ No newline at end of file diff --git a/hetu-docs/zh/indexer/hindex-statements.md b/hetu-docs/zh/indexer/hindex-statements.md new file mode 100644 index 000000000..4aba9c368 --- /dev/null +++ b/hetu-docs/zh/indexer/hindex-statements.md @@ -0,0 +1,65 @@ + +# 使用 + +索引命令行接口集成于`hetu-cli`中, 在安装目录的`bin`目录下运行。 + + +## 创建 +索引创建方法如下: +```roomsql +CREATE INDEX [ IF NOT EXISTS ] index_name +USING [ BITMAP | BLOOM | BTREE | MINMAX ] +ON tbl_name (col_name) +WITH ( "level" = ['STRIPE', 'PARTITION'], "bloom.fpp" = '0.001', [, …] ) +WHERE predicate; +``` + +- `WHERE` 用于选择部分分区创建索引 +- `WITH` 用于设置索引属性。参见各个索引的文档来查看支持的配置 +- `"level"='STRIPE'` 如缺省,默认创建级别是STRIPE + +如果表是分区的,可以用一个等于表达式来指定一个创建的分区,或使用IN来指定多个。 +```roomsql +CREATE INDEX index_name USING bloom ON hive.schema.table (column1); +CREATE INDEX index_name USING bloom ON hive.schema.table (column1) WITH ("bloom.fpp"="0.01") WHERE p=part1; +CREATE INDEX index_name USING bloom ON hive.schema.table (column1) WHERE p in (part1, part2, part3); +``` + +## SHOW + +显示所有索引或只根据名字显示一个索引: +```roomsql +SHOW INDEX; +SHOW INDEX index_name; +``` + +## DROP + +根据名字删除一条索引: +```roomsql +DROP INDEX index_name +WHERE predicate; +``` + +- `WHERE` 表达式用于只删除索引的几个分区。但是,如果在创建时是全表创建的索引,则只删除部分的索引将不可用(只能整条删除)。 + +```roomsql +DROP INDEX index_name where p=part1; +``` + +删除的索引不会立即被从服务器的缓存中清除,直到下一次刷新缓存。刷新时间与设置的缓存加载延迟有关,通常在几秒钟左右。 + +## 资源使用说明 + +### 磁盘使用 +启发式索引使用本地临时文件夹存储创建的索引,然后打包上传至hdfs。因此,它需要临时文件夹(例如,linux上的`/tmp`)挂载的磁盘分区在本地有足够的可用空间。如果挂载的磁盘分区可用空间不足,用户可以在worker节点的`jvm.config`中通过`-Djava.io.tmpdir`来指定使用的临时路径: + +``` +-Djava.io.tmpdir=/path/to/another/dir +``` + +下面的公式给出了一个对于Bloom索引占用磁盘空间的大致估计。Bloom索引使用的空间大致与用于创建索引的表的大小成正比,同时与指定的`fpp`值的对数相反数成正比。因此,更小的fpp值和更大的数据集会使得创建的索引更大: + +索引大小 = -log(fpp) * 表占用空间 * C + +系数C还与其他许多因素相关,例如创建索引的列占表总数据的比重,但这些因素的影响应当不如fpp和表的大小重要,且变化较小。作为一个典型的拥有几个列的数据表,这个系数C在0.04左右。这就是说,为一个100GB的数据表的一列创建一个`fpp=0.001`的索引大致需要12GB磁盘空间,而创建`fpp=0.0001`的索引则需要16GB左右。 diff --git a/hetu-docs/zh/indexer/indexer-cli.md b/hetu-docs/zh/indexer/indexer-cli.md deleted file mode 100644 index d05c2945d..000000000 --- a/hetu-docs/zh/indexer/indexer-cli.md +++ /dev/null @@ -1,95 +0,0 @@ - -# 索引命令行接口 - -## 用法 - -索引命令行接口集成于`hetu-cli`中, 在安装目录的`bin`目录下运行。 - -命令的使用方式如下: -```roomsql -CREATE INDEX [ IF NOT EXISTS ] index_name -USING [ BITMAP | BLOOM | MINMAX ] -ON tbl_name (col_name) -WITH ( "bloom.fpp" = '0.001', [, …] ) -WHERE predicate; -``` - -显示所有索引或特定的索引名称的方法如下: -```roomsql -SHOW INDEX; -SHOW INDEX index_name; -``` - -通过索引名称删除索引的方法如下: -```roomsql -DROP INDEX index_name; -``` - -## 示例 - -路径配置白名单:["/tmp", "/opt/hetu", "/opt/openlookeng", "/etc/hetu", "/etc/openlookeng", 工作目录] - -`etc` 目录包含config.properties,在指定config时,我们需要写绝对路径,该路径必须是白名单中路径的子目录 - -### 创建索引 - -``` shell -$ java -jar ./hetu-cli-*.jar --config /xxx/etc --execute 'CREATE INDEX index_name USING bloom ON hive.schema.table (column1) WITH ("bloom.fpp"="0.01", debugEnabled=true) WHERE p=part1' -``` - -### 显示索引 - -``` shell -$ java -jar ./hetu-cli-*.jar --config /xxx/etc --execute "SHOW INDEX index_name" -$ java -jar ./hetu-cli-*.jar --config /xxx/etc --execute "SHOW INDEX" -``` - -### 删除索引 - -``` shell -$ java -jar ./hetu-cli-*.jar --config /xxx/etc --execute "DROP INDEX index_name" -``` - -*注意*: 删除索引命令不会将索引文件从hetu server的内存中清除。意味着索引会被继续使用,直到达到`hetu.heuristicindex.filter.cache.ttl`所设置的值或者hetu server被重启. - - -## 资源使用说明 - -### 内存 - -默认情况下,将使用默认的JVMMaxHeapSize(`java -XX:+PrintFlagsFinal -version | grep MaxHeapSize`)。为了提高性能,建议增大MaxHeapSize的取值。可以通过设置-Xmx值来实现: - - -``` shell -export JAVA_TOOL_OPTIONS="-Xmx100G" -``` - -在此示例中,MaxHeapSize被设置为100 GB。 - -### 磁盘使用 -启发式索引使用本地临时文件夹存储创建的索引,然后打包上传至hdfs。因此,它需要临时文件夹(例如,linux上的`/tmp`)挂载的磁盘分区在本地有足够的可用空间。如果挂载的磁盘分区可用空间不足,用户可以在运行命令行时通过`-Djava.io.tmpdir`来指定使用的临时路径: -```bash -java -Djava.io.tmpdir=/path/to/another/dir -jar ./hetu-cli-*.jar -``` - -下面的公式给出了一个对于Bloom索引占用磁盘空间的大致估计。Bloom索引使用的空间大致与用于创建索引的表的大小成正比,同时与指定的`fpp`值的对数相反数成正比。因此,更小的fpp值和更大的数据集会使得创建的索引更大: - -索引大小 = -log(fpp) * 表占用空间 * C - -系数C还与其他许多因素相关,例如创建索引的列占表总数据的比重,但这些因素的影响应当不如fpp和表的大小重要,且变化较小。作为一个典型的拥有几个列的数据表,这个系数C在0.04左右。这就是说,为一个100GB的数据表的一列创建一个`fpp=0.001`的索引大致需要12GB磁盘空间,而创建`fpp=0.0001`的索引则需要16GB左右。 - -### 并行索引 - -如果在一台机器上为一个大表创建索引的速度太慢,则可以在不同的机器上并行为不同的分区创建索引。只要保证这些并行创建的分区不冲突即可。例如: - -在机器1上: - -``` bash -$ java -jar ./hetu-cli-*.jar --config /xxx/etc --execute 'CREATE INDEX index_name USING bloom ON hive.schema.table (column1) WITH ("bloom.fpp"="0.01") WHERE p=part1' -``` - -在机器2上: - -``` shell -$ java -jar ./hetu-cli-*.jar --config /xxx/etc --execute 'CREATE INDEX index_name USING bloom ON hive.schema.table (column1) WITH ("bloom.fpp"="0.01") WHERE p=part2' -``` diff --git a/hetu-docs/zh/indexer/minmax.md b/hetu-docs/zh/indexer/minmax.md index a83cde6bb..0f01d41ff 100644 --- a/hetu-docs/zh/indexer/minmax.md +++ b/hetu-docs/zh/indexer/minmax.md @@ -1,20 +1,41 @@ -# Minmax索引 +# MinMax索引 + +MinMax索引简单地记录数据的最大和最小值,占用空间极小。 +因此,这一索引仅仅能被用于已经排序的数据列。 + +## 过滤 + +1. MinMax索引用于调度时的分片过滤,被coordinator节点使用。 + +## 选择适用的列 + +MinMax索引仅仅能被用于已经排序的数据列。例如,ID或年龄. + +## 支持的运算符 + + = Equality + > Greater than + >= Greater than or equal + < Less than + <= Less than or equal ## 用例 -MinMax 索引用于分片过滤,仅被**coordinator**节点使用。 - -如果查询中作为谓词一部分的列存在此索引,则引擎可以通过筛选预定Splits来提高性能,类似于Bloom索引。 - -例如,如果索引在列 - -`age` - -查询语句为 - +创建索引: ```sql -select * from table where age > 50 +create index idx using minmax on hive.hindex.users (age); +create index idx using minmax on hive.hindex.users (age) where regionkey=1; +create index idx using minmax on hive.hindex.users (age) where regionkey in (3, 1); ``` -*提示:对索引列中的数据进行排序将提供最佳结果。* +* 假设表已按照`regionkey`列分区 + +使用索引: +```sql +select name from hive.hindex.users where age=20 +select name from hive.hindex.users where age>20 +select name from hive.hindex.users where age<20 +select name from hive.hindex.users where age>=20 +select name from hive.hindex.users where age<=20 +``` \ No newline at end of file diff --git a/hetu-docs/zh/indexer/new-index.md b/hetu-docs/zh/indexer/new-index.md new file mode 100644 index 000000000..851c69ff6 --- /dev/null +++ b/hetu-docs/zh/indexer/new-index.md @@ -0,0 +1,48 @@ +# 创建自定义索引 + +## 基本概念 + +### ID + +每一个索引类型都必须有一个`ID`变量作为其唯一标识符。这一名称将用于CLI,服务器配置,存储索引的文件路径中等各种场合,用于唯一地确定这一索引类型。 + +`Index`接口的`getID()`方法会将索引的ID返回给它的使用者。 + +### Level (数据)层级 + +启发式索引用各种不同的方法,存储了在原始数据之外额外并且通常更小的信息,用于提高随机查询的效率。因此,每一条索引都必须有它作用的数据域范围。例如,如果一个索引 +记录了数据集的"最大"数值,那这一"最大"数值必须拥有它作用的范围(可以是一组数据行,也可以是一个数据分区,甚至整张数据表的最大值)。当创建一个新的索引类型是,必须 +实现`Set getSupportedIndexLevels();` 方法来告知它可以支持的数据层级。这些层级由`Index`接口中的一个枚举类型定义。 + +## 接口概览 + +### 索引方法 + +除了上面提到的方法以外,这一段落将介绍其他几个实现新索引类型最重要的方法。要获取`Index`接口的完整文档,请参阅源代码的Java Doc。 + +`Index`接口有两个最重要的方法: + +```java +boolean matches(Object expression) throws UnsupportedOperationException; + + Iterator lookUp(Object expression) throws UnsupportedOperationException; +``` + +第一个`matches()`方法接收一个表达式对象,并返回基于索引存储的信息,表达式对应的数据是否可能存在。例如,如果一个索引标记了数据中的最大值,那他可以容易地判断`col_val > 5`是否可能成立。 + +第二个方法`lookUp()`不是必须的。在返回数据是否可能存在以外,他还能返回一个迭代器来返回数据可能存在的位置。对于一个索引,它的`matches()`方法和`lookUp().hasNext()`应当总是返回相同的结果。 + +### 插入和存取索引 + +下面的几个方法用于向一个索引中添加值,以及在磁盘上存储/读取索引实例: + +```java +boolean addValues(Map> values) throws IOException; + +Index deserialize(InputStream in) throws IOException; + +void serialize(OutputStream out) throws IOException; +``` + +这些方法的使用非常直观。为了更好地理解他们的用法,`MinMaxIndex`的源代码可以作为一个很好的例子。在这个索引中,添加数据仅仅需要通过新的数据更新`max`和`min`变量即可。 +`serialize()/deserialize()`方法则只需要向/从磁盘写入/读取最大和最小值这两个值。 \ No newline at end of file diff --git a/hetu-docs/zh/indexer/overview.md b/hetu-docs/zh/indexer/overview.md index 192d83a29..75d08c61d 100644 --- a/hetu-docs/zh/indexer/overview.md +++ b/hetu-docs/zh/indexer/overview.md @@ -14,50 +14,57 @@ ## 使用场景 -当前,启发式索引支持ORC存储格式的hive数据源,帮助减少读取的分段或行数。 +**当前,启发式索引支持ORC存储格式的hive数据源。** -### 1.查询过程中过滤预定分段 +### 1.查询过程中过滤预定分片 + +支持的索引:Bloom, BTree, MinMax 当引擎需要调度一个TableScan操作时,它可以调度worker节点上的Split。这些Split负责读取部分源数据。但是如果应用了谓词,则并非所有Split都会返回数据。 +例如,`select * from test_base where j1='070299439'` + 通过为谓词列保留外部索引,启发式索引可以确定每个Split是否包含正在搜索的值,并且只对可能包含该值的Split安排读操作。 ![indexer_filter_splits](../images/indexer_filter_splits.png) -### 2.读取ORC文件时提前筛选块 +### 2.读取ORC文件时提前筛选Stripes -当需要从ORC文件中读取数据时,使用ORCRecordReader读取器。此读取器从数据条带批量(例如1024行)读取数据,然后形成页。但是,如果有一个谓词存在,那么就不需要批量读取中的所有条目,有些条目可能会在稍后被Filter运算符过滤掉。 +支持的索引:Bloom, MinMax -通过为谓词列保留外部位图索引,启发式索引甚至可以在应用Filter运算符之前筛选出与谓词不匹配的行。 +与分片过滤类似,当使用Hive Connector读取ORC文件时,Stripe可以被提前过滤来减少读取的数据量,从而提升查询性能。 + +### 3.读取ORC文件时筛选行 + +支持的索引:Bitmap + +当需要从ORC文件中读取数据时,如果有一个谓词存在,那么就不需要批量读取中的所有行。 + +通过为谓词列保留外部位图索引,将实现只读取匹配当行,来提升内存和处理器表现。在服务器高并发时提升尤其明显。 ## 示例教程 -这一教程将通过一个示例查询语句来展示索引的用法。 +这一教程将通过一个示例查询语句来展示索引的用法。完整的配置请参见[Properties](../admin/properties.md)。 -### 确定索引建立的列 - -对于这样的语句: - - SELECT * FROM table1 WHERE id="abcd1234"; - -如果id比较唯一,bloom索引可以大大较少读取的分段数量。 - -在本教程中我们将以这个语句为例。 - -### 配置索引 +### 1. 配置索引 在 `etc/config.properties` 中加入这些行: -路径配置白名单:["/tmp", "/opt/hetu", "/opt/openlookeng", "/etc/hetu", "/etc/openlookeng", 工作目录] - -注意:避免选择根目录;路径不能包含../;如果配置了node.data_dir,那么当前工作目录为node.data_dir的父目录; - 如果没有配置,那么当前工作目录为openlookeng server的目录 - hetu.heuristicindex.filter.enabled=true - hetu.heuristicindex.filter.cache.max-memory=2GB + hetu.heuristicindex.filter.cache.max-memory=10GB hetu.heuristicindex.indexstore.uri=/opt/hetu/indices hetu.heuristicindex.indexstore.filesystem.profile=index-store-profile - + +路径配置白名单:["/tmp", "/opt/hetu", "/opt/openlookeng", "/etc/hetu", "/etc/openlookeng", 工作目录] + +避免选择根目录;路径不能包含../;如果配置了node.data_dir,那么当前工作目录为node.data_dir的父目录;如果没有配置,那么当前工作目录为openlookeng server的目录 + +**注意**: +- `LOCAL` 本地文件系统只应该被用于本地测试,或单节点部署情形。(否则索引文件将无法在机器之间共享) +- `HDFS` 应用于生产环境来在集群中共享数据。 +- 所有节点必须有相同的文件系统配置。 +- 在服务器运行中可以通过`set session heuristicindex_filter_enabled=false;`关闭启发式索引。 + 然后在`etc/filesystem/index-store-profile.properties`中创建一个HDFS描述文件, 其中`index-store-profile`是上面使用的名字: fs.client.type=hdfs @@ -67,18 +74,80 @@ 如果HDFS集群开启了KERBEROS验证,还需要配置`hdfs.krb5.conf.path, hdfs.krb5.keytab.path, hdfs.krb5.principal`. -在上面这个例子中使用了HDFS作为存储索引文件的位置,这使得索引可以在多个Hetu服务器间共享。如果要使用本地磁盘来存储索引,只要将 `index-store-profile.properties` 的内容改为: +### 2. 确定索引建立的列 - fs.client.type=local +对于这样的语句: + + SELECT * FROM table1 WHERE id="abcd1234"; + +如果id比较唯一,bloom索引可以大大较少读取的分段数量。 + +在本教程中我们将以这个语句为例。 + +### 3. 创建索引 + +要创建索引, 在命令行中输入: + + CREATE INDEX index_name USING bloom ON table1 (column); -注意:可以在`etc/filesystem`中配置多个不同名字的描述文件, 例如多个HDFS和一个Local,这样就可以通过改变`hetu.heuristicindex.indexstore.filesystem.profile`来在他们之中快速切换。 +### 4. 运行语句 -### 创建索引 +完成上面的操作后,再次在Hetu服务器运行这个语句,服务器将在后台自动加载索引。接下来的语句将会从中获得性能提升。 -要创建索引,首先将工作目录cd至安装目录的`bin`文件夹,然后运行: +## 索引语句 - java -jar ./hetu-cli-*.jar --config --execute 'CREATE INDEX index_name USING bloom ON table1 (column)' +参见 [Heuristic Index Statements](./hindex-statements.md). + +----- + +## 支持的索引类型 + +| 索引 ID | 过滤类型 | 最适用的列 | 支持的运算符 | 注释 | 用例 | +|----------|-----------------|--------------------------------------------|---------------------------------------|---------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [Bloom](./bloom.md) | Split
Stripe | 大量不同数据值
(如ID) | `=` `IN` | | `create index idx using bloom on hive.hindex.users (id);`
`select name from hive.hindex.users where id=123` | +| [Btree](./btree.md) | Split | 大量不同数据值
(如ID) | `=` `>` `>=` `<` `<=` `IN` `BETWEEN` | 表必须被分区 | `create index idx using btree on hive.hindex.users (id) where regionkey IN (1,4) with ("level"='partition')`
(假设表根据regionkey分区)
`select name from hive.hindex.users where id>123` | +| [MinMax](./minmax.md) | Split
Stripe | 列数据被排序 | `=` `>` `>=` `<` `<=` | | `create index idx using bloom on hive.hindex.users (age);`
(假设数据根据年龄已排序)
`select name from hive.hindex.users where age>25` | +| [Bitmap](./bitmap.md) | Row | 少量不同数据值
(如性别) | `=` `IN` | | `create index idx using bitmap on hive.hindex.users (gender);`
`select name from hive.hindex.users where gender='female'` | + +**注意:** 包含不支持的运算符的语句依然会正常运行,但是不会从启发式索引中获得性能提升。 + + +## 选择索引类型 + +启发式索引用于根据谓词表达式过滤数据。请根据下面的决策流程图选择适用于数据列的最佳索引。 + +Cardinality 是指数据集中值域的大小。例如,`ID`列通常有很大的cardinality, +而`employeeType`列通常cardinality很小(如 Manager, Developer, Tester)。 + +![index-decision](../images/index-decision.png) + +用例: + +1. `SELECT id FROM employees WHERE site = 'lab';` + + 在这个语句中`site`的cardinality很小(没有很多不同的地点取值)。 因此,**Bitmap索引**比较适合。 + +2. `SELECT * FROM visited WHERE id = '34857' AND date < '2020-01-01';` + + 在这个语句中`id`有很高的cardinality (每一个ID是唯一的)。同时,表根据`date`已经分区。因此**Btree索引**比较适合。 -### 运行语句 +3. `SELECT * FROM salaries WHERE salary > 50251.40;` -完成上面的操作后,再次在Hetu服务器运行这个语句,服务器将在后台自动加载索引。在此期间如果反复执行同一语句,应该观察到分段的数量不断降低,最后降至一个很小的值。 \ No newline at end of file + 在这个语句中`salary`有很高的cardinality(每个员工的收入总有些许不同)。假设表已经根据`salary`排序, 则**MinMax索引**最为适合。 + +4. `SELECT * FROM assets WHERE id = 50;` + + 在这个语句中`id`有很高的cardinality (每一个ID是唯一的)。但是,表没有分区。因此**Bloom索引**比较适合。 + +5. `SELECT * FROM phoneRecords WHERE phone='1234567890' and type = 'outgoing' and date > '2020-01-01';` + + 在这个语句中`phone`有很高的cardinality (即使有重复的电话,绝大部分号码总是不同的), `type`的cardinality较低 (只有两种:呼出/呼入), + 同时数据根据`date`已分区。因此,在`phone`上创建**Btree索引**并在`type`上创建**Bitmap索引**最为适合。 + +## 添加自定义的索引类型 + +参见 [Adding your own Index Type](./new-index.md). + +## 权限控制 + +参见 [Built-in System Access Control](../security/built-in-system-access-control.md). diff --git a/hetu-docs/zh/security/built-in-system-access-control.md b/hetu-docs/zh/security/built-in-system-access-control.md index 6c515221d..1021f422c 100644 --- a/hetu-docs/zh/security/built-in-system-access-control.md +++ b/hetu-docs/zh/security/built-in-system-access-control.md @@ -180,4 +180,31 @@ security.refresh-period=1s } ] } +``` + +### 启发式索引控制规则 + +这些规则控制了允许的启发式索引操作。 + +每条规则由以下部分组成: + +- `user` (必要): 匹配用户名称的正则表达式。默认值:`.*`. +- `privileges` (可选): 授予用户的权限 (`ALL`, `SHOW`, `CREATE`, `DROP`, `RENAME`, and `UPDATE`). 默认值 `ALL`. + +在下面这个例子中,用户`tom`只能执行`SHOW INDEX`或`CREATE INDEX`指令。 +用户`admin`可以执行`CREATE INDEX`, `SHOW INDEX`, `DROP INDEX`等所有指令. + +```json +{ + "indexAccess": [ + { + "user": "tom", + "privileges": ["SHOW", "CREATE"] + }, + { + "user": "admin", + "privileges": ["ALL"] + } + ] +} ``` \ No newline at end of file