-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs/design: add proposal for invisible index #15338
Changes from all commits
5f61ac2
d0490eb
115916c
9f50b95
612444d
86f098c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,91 @@ | ||||||
# Proposal: Invisible index | ||||||
|
||||||
- Author(s): [Deardrops](https://github.com/Deardrops), [wjhuang2016](https://github.com/wjhuang2016) | ||||||
- Last updated: Mar. 12, 2020 | ||||||
- Discussion at: https://github.com/pingcap/tidb/issues/9246 | ||||||
|
||||||
## Abstract | ||||||
|
||||||
MySQL supports [Invisible indexes](https://dev.mysql.com/doc/refman/8.0/en/invisible-indexes.html); that is, indexes that are not used by the optimizer. | ||||||
|
||||||
This is a useful feature for dropping an index in a safe way. Invisible indexes make it possible to test the effect of removing an index on query performance, without making a destructive change that must be undone should the index turn out to be required. Dropping and re-adding an index can be expensive for a large table, whereas making it invisible and visible are fast, in-place operations. | ||||||
|
||||||
Support the option of `VISIBLE | INVISIBLE`. | ||||||
``` | ||||||
CREATE [...] INDEX index_name | ||||||
[index_type] | ||||||
ON tbl_name (key_part,...) | ||||||
[index_option] | ||||||
|
||||||
index_option: | ||||||
{VISIBLE | INVISIBLE} | ||||||
``` | ||||||
|
||||||
Also, consider the following: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
- Display information about invisible indexes in the output of `INFORMATION_SCHEMA.STATISTICS` or `SHOW INDEX`. | ||||||
- Index hints need to report errors when used in invisible indexes. | ||||||
- The primary key cannot be set to an invisible index. | ||||||
|
||||||
## Background | ||||||
|
||||||
Index has a great influence on the performance of the database. Whether there is an index or whether the optimizer chooses the right index determines the performance of reading and writing the database to a great extent. In some cases, we would like to know the impact of deleting an index on the read-write performance of the database. At present, our method is to tell the optimizer to ignore the index through Index Hint. Although this method can achieve the goal, it is not practical to modify all SQL statements. | ||||||
|
||||||
## Proposal | ||||||
|
||||||
Adding an option (visible or not) to the index. If it is not visible, it's called **Invisible Index**. Invisible Index cannot be used by the optimizer (with the `use_invisible_indexes` switch on), but the index is maintained during DML operations. For a query statement, invisible index has the same effect as ignoring the index through Index Hint. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
The option `INVISIBLE` of an index can be changed by using the following DDL statement: | ||||||
|
||||||
``` | ||||||
ALTER TABLE table_name ALTER INDEX index_name { INVISIBLE | VISIBLE }; | ||||||
``` | ||||||
|
||||||
Or set option `INVISIBLE` when creating an index: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
``` | ||||||
CREATE INDEX index_name ON table_name(key) [ INVISIBLE | VISIBLE ]; | ||||||
``` | ||||||
|
||||||
`INVISIBLE`, `VISIBLE` is as part of the index option, they can also be set when creating a table. | ||||||
|
||||||
In order to know whether an index is invisible, it can be read from the `INFORMATION_SCHEMA.STATISTICS` table or through the `SHOW INDEX` command. | ||||||
|
||||||
In addition, add a new flag `use_invisible_indexes` in system variable `optimizer_switch`, which determine whether the option `INVISIBLE` takes effect. If `use_invite_indexes` is on, the optimizer can still use invisible index. | ||||||
|
||||||
A table with no explicit primary key may still have an effective implicit primary key if it has any UNIQUE indexes on NOT NULL columns. In this case, the first such index places the same constraint on table rows as an explicit primary key and that index cannot be made invisible. | ||||||
|
||||||
## Rationale | ||||||
|
||||||
Another solution for implement invisible indexes is: Indicate invisibility by DDL state `WriteOnly`. This solution has the following problems: | ||||||
|
||||||
- The logic of schema change needs to be changed, which is relatively complicated to implement. | ||||||
- Cannot distinguish between indexes that are currently in WriteOnly and invisible indexes. | ||||||
- Handling the switch is troublesome. | ||||||
|
||||||
## Compatibility and Migration Plan | ||||||
|
||||||
This the a new feature and it's absolutly compatible with old TiDB versions, also, it's not impact any data migration. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
The syntax and functions are basically compatible with MySQL. Expect one: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
When use invisible index in `SQL Hint`, and set `use_invisible_indexes = false`, MySQL allow use the invisible index. | ||||||
But in TiDB, It's **not allowed**, and will throw a `Unresolved name` error, Because the behavior is more reasonable. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
## Implementation | ||||||
|
||||||
- Add syntax support in parser | ||||||
- Add a new column `IS_VISIBLE` in `information_schema.statistics` | ||||||
- Add a new column `VISIBLE` in `SHOW INDEX FROM table` statement | ||||||
- Show invisiable column infomations in `SHOW CREATE TABLE` statement | ||||||
- Add `use_invisible_indexes` in system variable `@@optimizer_switch` | ||||||
- Add new error message `ERROR 3522 (HY000): A primary key index cannot be invisible` | ||||||
- Ignore invisible index in optimizer and add unit tests | ||||||
|
||||||
## Testing Plan | ||||||
|
||||||
- Unit test | ||||||
- Port All mysql test related to invisible index | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
## Open issues | ||||||
|
||||||
https://github.com/pingcap/tidb/issues/9246 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.