|
1 | 1 |
|
2 | 2 | # Серийные типы данных
|
3 | 3 |
|
4 |
| -Серийные типы данных представляют собой целые числа, но с дополнительным механизмом генерации значений. Эти типы данных используются для создания автоинкрементных колонок, а именно для каждой новой строки, добавляемой в таблицу, будет автоматически генерироваться уникальное значение для такой колонки (подобно типу [SERIAL](https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-SERIAL) в PostgreSQL или свойству [AUTO_INCREMENT](https://dev.mysql.com/doc/refman/9.0/en/example-auto-increment.html) в MySQL). |
| 4 | +Серийные типы данных представляют собой целые числа, но с дополнительным механизмом генерации значений. Эти типы данных используются для создания автоинкрементных колонок, а именно - для каждой новой строки, добавляемой в таблицу, будет автоматически генерироваться уникальное значение для такой колонки (подобно типу [SERIAL](https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-SERIAL) в PostgreSQL или свойству [AUTO_INCREMENT](https://dev.mysql.com/doc/refman/9.0/en/example-auto-increment.html) в MySQL). |
| 5 | + |
| 6 | +## Описание |
| 7 | + |
| 8 | +При определении такого типа для колонки создаётся отдельный схемный объект `Sequence`, привязанный к этой колонке и являющийся генератором последовательности, из которого извлекаются значения. Этот объект является приватным и скрыт от пользователя. `Sequence` будет уничтожен вместе с таблицей. |
| 9 | + |
| 10 | +Значения последовательности начинаются с единицы, выдаются с шагом, равным единице, и ограничены в зависимости от используемого типа. |
| 11 | + |
| 12 | +> **Примечание:** |
| 13 | +> Колонки типа `Serial` поддерживаются как для колонок, входящих в состав первичного ключа, так и для неключевых колонок. |
| 14 | +> |
| 15 | +> Однако такие колонки нельзя [изменить](../syntax/alter_table/family#mod-column-groups) или [удалить](../syntax/alter_table/columns.md) из таблицы — |
| 16 | +> при попытке выполнить эти операции будет возвращена ошибка. |
| 17 | +
|
| 18 | +| Тип | Максимальное значение | Тип значения | |
| 19 | +|---------------|-----------------------|--------------| |
| 20 | +| `SmallSerial` | $2^{15}–1$ | `Int16` | |
| 21 | +| `Serial2` | $2^{15}–1$ | `Int16` | |
| 22 | +| `Serial` | $2^{31}–1$ | `Int32` | |
| 23 | +| `Serial4` | $2^{31}–1$ | `Int32` | |
| 24 | +| `Serial8` | $2^{63}–1$ | `Int64` | |
| 25 | +| `BigSerial` | $2^{63}–1$ | `Int64` | |
| 26 | + |
| 27 | +При переполнении `Sequence` на вставке будет возвращаться ошибка: |
| 28 | + |
| 29 | +```text |
| 30 | +Error: Failed to get next val for sequence: /dev/test/users/_serial_column_user_id, status: SCHEME_ERROR |
| 31 | + <main>: Error: sequence [OwnerId: <some>, LocalPathId: <some>] doesn't have any more values available, code: 200503 |
| 32 | +``` |
| 33 | + |
| 34 | +Отметим, что следующее значение выдаётся генератором до непосредственной вставки в таблицу и уже будет считаться использованным, даже если строка, содержащая это значение, не была успешно вставлена, например, при откате транзакции. Поэтому множество значений такой колонки может содержать пропуски и состоять из нескольких промежутков. |
| 35 | + |
| 36 | +Для таблиц с автоинкрементными колонками поддержаны операции [copy](../../../reference/ydb-cli/tools-copy.md), [rename](../../../reference/ydb-cli/commands/tools/rename.md), [dump](../../../reference/ydb-cli/export-import/tools-dump.md), [restore](../../../reference/ydb-cli/export-import/import-file.md) и [import](../../../reference/ydb-cli/export-import/import-s3.md)/[export](../../../reference/ydb-cli/export-import/export-s3.md). |
5 | 37 |
|
6 | 38 | ## Пример использования
|
7 | 39 |
|
| 40 | +Cледует обратить внимание на правильный выбор колонок для [PRIMARY KEY](../../../dev/primary-key/row-oriented.md). Для масштабируемости нагрузки и высокой производительности стоит избегать записи строк с монотонно возрастающими первичными ключами. В этом случае все записи будут попадать в последнюю партицию, и вся нагрузка будет приходиться на один сервер. |
| 41 | + |
| 42 | +Например, в качестве первого элемента ключа использовать можно хеш от всего первичного ключа либо его части, чтобы равномерно распределять данные по партициям кластера. |
| 43 | + |
8 | 44 | ``` yql
|
9 | 45 | CREATE TABLE users (
|
| 46 | + user_hash Uint64, |
10 | 47 | user_id Serial,
|
11 | 48 | name Utf8,
|
12 | 49 | email Utf8,
|
13 |
| - PRIMARY KEY (user_id) |
| 50 | + PRIMARY KEY (user_hash, user_id) |
14 | 51 | );
|
15 | 52 | ```
|
16 | 53 |
|
| 54 | +Хеш для поля `user_hash` можно рассчитать на стороне приложения, например, используя хеш-функцию от `email`. |
| 55 | + |
17 | 56 | ``` yql
|
18 |
| -UPSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com'); |
19 |
| -INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com'); |
20 |
| -REPLACE INTO users (name, email) VALUES ('John', 'john@example.com'); |
| 57 | +UPSERT INTO users (user_hash, name, email) VALUES (123456789, 'Alice', 'alice@example.com'); |
| 58 | +INSERT INTO users (user_hash, name, email) VALUES (987654321, 'Bob', 'bob@example.com'); |
| 59 | +REPLACE INTO users (user_hash, name, email) VALUES (111111111, 'John', 'john@example.com'); |
21 | 60 | ```
|
22 | 61 |
|
23 | 62 | ``` yql
|
24 | 63 | SELECT * FROM users;
|
25 | 64 | ```
|
26 | 65 |
|
27 |
| -| email | name | user_id | |
28 |
| -|---------------------|-------|---------| |
29 |
| -| `alice@example.com` | Alice | 1 | |
30 |
| -| `bob@example.com` | Bob | 2 | |
31 |
| -| `john@example.com` | John | 3 | |
| 66 | +Результат (значения `user_hash` приведены для примера): |
32 | 67 |
|
33 |
| -Можно самостоятельно указать значение `Serial` колонки при вставке, в этом случае вставка будет выполняться, как с обычной целочисленной колонкой, и `Sequence` затрагиваться при таком запросе никак не будет: |
| 68 | +| user_hash | email | name | user_id | |
| 69 | +|-------------|---------------------|-------|---------| |
| 70 | +| 123456789 | alice@example.com | Alice | 1 | |
| 71 | +| 987654321 | bob@example.com | Bob | 2 | |
| 72 | +| 111111111 | john@example.com | John | 3 | |
| 73 | + |
| 74 | +Можно самостоятельно указать значение `Serial`-колонки при вставке, например для восстановления данных. В этом случае вставка будет выполняться, как с обычной целочисленной колонкой, и `Sequence` затрагиваться при таком запросе никак не будет: |
34 | 75 |
|
35 | 76 | ``` yql
|
36 |
| -UPSERT INTO users (user_id, name, email) VALUES (4, 'Peter', 'peter@example.com'); |
| 77 | +UPSERT INTO users (user_hash, user_id, name, email) VALUES (222222222, 10, 'Peter', 'peter@example.com'); |
37 | 78 | ```
|
38 | 79 |
|
39 |
| -## Описание |
40 |
| - |
41 |
| -Только колонки, участвующие в первичном ключе таблиц, могут иметь тип `Serial`. |
42 |
| - |
43 |
| -При определении такого типа для колонки создаётся отдельный схемный объект `Sequence`, привязанный к этой колонке и являющийся генератором последовательности, из которого извлекаются значения. Этот объект является приватным и скрыт от пользователя. `Sequence` будет уничтожен вместе с таблицей. |
44 |
| - |
45 |
| -Значения последовательности начинаются с единицы, выдаются с шагом, равным единице, и ограничены в зависимости от используемого типа. |
| 80 | +### Пример неудачной схемы |
46 | 81 |
|
47 |
| -| Тип | Максимальное значение | Тип значения | |
48 |
| -|---------------|-----------------------|--------------| |
49 |
| -| `SmallSerial` | $2^{15}–1$ | `Int16` | |
50 |
| -| `Serial2` | $2^{15}–1$ | `Int16` | |
51 |
| -| `Serial` | $2^{31}–1$ | `Int32` | |
52 |
| -| `Serial4` | $2^{31}–1$ | `Int32` | |
53 |
| -| `Serial8` | $2^{63}–1$ | `Int64` | |
54 |
| -| `BigSerial` | $2^{63}–1$ | `Int64` | |
55 |
| - |
56 |
| -При переполнении `Sequence` на вставке будет возвращаться ошибка: |
57 |
| - |
58 |
| -```text |
59 |
| -Error: Failed to get next val for sequence: /dev/test/users/_serial_column_user_id, status: SCHEME_ERROR |
60 |
| - <main>: Error: sequence [OwnerId: <some>, LocalPathId: <some>] doesn't have any more values available, code: 200503 |
| 82 | +``` yql |
| 83 | +CREATE TABLE users_bad ( |
| 84 | + user_id Serial, |
| 85 | + name Utf8, |
| 86 | + email Utf8, |
| 87 | + PRIMARY KEY (user_id) |
| 88 | +); |
61 | 89 | ```
|
62 | 90 |
|
63 |
| -Отметим, что следующее значение выдаётся генератором до непосредственной вставки в таблицу и уже будет считаться использованным, даже если строка, содержащая это значение, не была успешно вставлена, например, при откате транзакции. Поэтому множество значений такой колонки может содержать пропуски и состоять из нескольких промежутков. |
64 |
| - |
65 |
| -Для таблиц с автоинкрементными колонками поддержаны операции [copy](../../../reference/ydb-cli/tools-copy.md), [dump](../../../reference/ydb-cli/export-import/tools-dump.md), [restore](../../../reference/ydb-cli/export-import/import-file.md) и [import](../../../reference/ydb-cli/export-import/import-s3.md)/[export](../../../reference/ydb-cli/export-import/export-s3.md). |
| 91 | +В следующем примере автоинкрементная колонка является единственным и первым элементом ключа — это приведёт к неравномерной нагрузке и узкому месту на последней партиции. |
66 | 92 |
|
0 commit comments