En esta página, se analizan las estrategias que se deben usar para generar valores de clave primaria en tu tabla con expresiones de valor predeterminado. La información de esta página se aplica a las bases de datos con dialecto de GoogleSQL y a las bases de datos con dialecto de PostgreSQL. Estas estrategias tienen los siguientes beneficios:
- Evitan los hotspots.
- Simplifican las migraciones desde otras bases de datos.
- Encapsulan la lógica de claves en la base de datos para que no tengas que preocuparte por administrarla en tu aplicación.
- En la mayoría de los casos, reemplazan la necesidad de crear y administrar tus propias secuencias.
Métodos para generar automáticamente claves primarias
Para generar automáticamente valores de clave primaria, puedes usar las siguientes estrategias en una columna que tenga expresiones DEFAULT:
- Una función UUID que genera valores de UUID versión 4.
- Columnas
IDENTITYque generan automáticamente valores de números enteros para columnas clave y no clave. SERIALen PostgreSQL yAUTO_INCREMENTen GoogleSQL, que son alias de lenguaje de definición de datos (DDL) para columnasIDENTITY.- Un objeto de esquema,
SEQUENCE, que tiene una opciónbit_reversed_positive.SEQUENCEestá disponible para GoogleSQL y PostgreSQL. - Una columna
rowidgenerada automáticamente para tablas que no tienen claves primarias definidas por el usuario.
Identificador único universal (UUID)
Spanner puede generar automáticamente un UUID versión 4 para usarlo como clave primaria. Los UUID funcionan bien para aplicaciones y tablas nuevas con muchas filas. Se distribuyen de manera uniforme en el espacio de claves, lo que evita los hotspots a gran escala. La generación de UUID puede crear una gran cantidad de valores (2122), y cada valor es efectivamente único. Por ejemplo, necesitarías 2.71 × 1018 valores para una probabilidad de colisión del 50% o 1 mil millones por segundo durante 86 años. Este amplio rango garantiza valores únicos cuando usas UUID en tablas grandes. Los UUID son únicos, ya sea que los generes en la base de datos o en el cliente. Te recomendamos que uses UUID cuando sea posible. Puedes combinar de forma segura UUID generados por el cliente y generados por Spanner en la misma tabla si los UUID generados por el cliente se serializan en minúscula, de acuerdo con RFC 4122.
Para una columna que necesita valores predeterminados, puedes usar la
NEW_UUID
función de GoogleSQL o la
gen_random_uuid()
función de PostgreSQL para generarlos. En el siguiente ejemplo, se muestra cómo crear una tabla en la que la columna clave FanId tiene un UUID generado en la columna de valor como su valor predeterminado.
GoogleSQL
CREATE TABLE Fans (
FanId UUID DEFAULT (NEW_UUID()),
Name STRING(MAX),
) PRIMARY KEY (FanId);
PostgreSQL
CREATE TABLE Fans (
FanId uuid DEFAULT gen_random_uuid(),
Name text,
PRIMARY KEY (FanId)
);
GoogleSQL
INSERT INTO Fans (Name) VALUES ('Melissa Garcia')
THEN RETURN FanId;
PostgreSQL
INSERT INTO fans (name) VALUES ('Melissa Garcia')
RETURNING fanid;
Esta instrucción muestra un resultado similar al siguiente:
| FanId |
|---|
| 6af91072-f009-4c15-8c42-ebe38ae83751 |
Para obtener más información sobre las funciones de UUID generadas, consulta la GoogleSQL o PostgreSQL.
Columnas IDENTITY
Con las columnas IDENTITY, puedes generar automáticamente valores de números enteros para columnas clave y no clave. Las columnas IDENTITY no requieren que mantengas manualmente una secuencia subyacente ni que administres la relación entre la columna y la secuencia subyacente. Cuando quitas una columna de identidad generada automáticamente, Spanner también borra automáticamente la secuencia subyacente.
Puedes usar columnas IDENTITY si proporcionas un valor de número entero inicial cuando generas la secuencia o si permites que Spanner genere la secuencia de números enteros por ti. Para proporcionar un valor de número entero inicial, debes usar la opción START
COUNTER WITH y un valor inicial INT64 positivo.
Spanner usa este valor para establecer el siguiente valor de su contador de secuencia interno generado automáticamente y revierte el valor antes de insertarlo en esta columna.
En Spanner, las columnas IDENTITY son compatibles con GoogleSQL y PostgreSQL.
GoogleSQL
En el siguiente ejemplo, se muestra cómo usar columnas IDENTITY para crear una columna de clave primaria de números enteros generada automáticamente para SingerId cuando se crea una tabla nueva con el comando CREATE TABLE:
CREATE TABLE Singers (
SingerId INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE),
Name STRING(MAX),
Rank INT64
) PRIMARY KEY (SingerId);
También puedes especificar el inicio del contador para la columna con la opción START COUNTER WITH. En el siguiente ejemplo, se crea una columna de números enteros generada automáticamente para SingerId que tiene valores positivos invertidos en bits y un contador interno que comienza en 1,000.
CREATE TABLE Singers (
SingerId INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000),
Name STRING(MAX),
Rank INT64
) PRIMARY KEY (SingerId);
PostgreSQL
En el siguiente ejemplo, se muestra cómo usar columnas IDENTITY para crear una columna de números enteros generada automáticamente para SingerId cuando se crea una tabla nueva con el comando CREATE
TABLE:
CREATE TABLE Singers (
SingerId bigint GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE),
Name text,
PRIMARY KEY (SingerId)
);
También puedes especificar el inicio del contador para la columna con la opción START
COUNTER WITH. En el siguiente ejemplo, se crea una columna de números enteros generada automáticamente para SingerId que genera valores positivos invertidos en bits y el contador interno, antes de la inversión en bits, comienza en 1,000.
CREATE TABLE Singers (
SingerId bigint GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000),
Name text,
PRIMARY KEY (SingerId)
);
SERIAL y AUTO_INCREMENT
Spanner admite SERIAL en PostgreSQL y
AUTO_INCREMENT en GoogleSQL, que son alias de DDL para IDENTITY
columnas y se usan para crear columnas de números enteros únicas.
Primero debes establecer la opción default_sequence_kind de la base de datos antes de usar SERIAL o AUTO_INCREMENT. Puedes usar la siguiente instrucción de SQL para establecer la opción default_sequence_kind de la base de datos:
GoogleSQL
ALTER DATABASE db SET OPTIONS (default_sequence_kind = 'bit_reversed_positive');
CREATE TABLE Singers (
id INT64 AUTO_INCREMENT PRIMARY KEY,
name STRING(MAX),
);
PostgreSQL
ALTER DATABASE db SET spanner.default_sequence_kind = 'bit_reversed_positive';
CREATE TABLE Singers (
id serial PRIMARY KEY,
name text
);
Debido a que SERIAL y AUTO_INCREMENT se asignan a columnas IDENTITY, no las verás cuando serialices tu esquema. Para este esquema, el resultado de GetDatabaseDDL sería el siguiente:
GoogleSQL
ALTER DATABASE db SET OPTIONS (default_sequence_kind = 'bit_reversed_positive');
CREATE TABLE Singers (
id INT64 GENERATED BY DEFAULT AS IDENTITY,
name STRING(MAX)
) PRIMARY KEY (id);
PostgreSQL
ALTER DATABASE db SET spanner.default_sequence_kind = 'bit_reversed_positive';
CREATE TABLE Singers (
id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL,
name character varying,
PRIMARY KEY(id)
);
Secuencia invertida en bits
Una secuencia invertida en bits es un objeto de esquema que produce una secuencia de números enteros y los invierte en bits. Este objeto usa la inversión de bits en un contador interno y privado de Spanner para garantizar la unicidad. Los valores invertidos en bits resultantes ayudan a evitar los hotspots a gran escala cuando se usan en una clave primaria.
En Spanner, usas sentencias DDL SEQUENCE junto con el
bit_reversed_positive atributo para crear, modificar o quitar una secuencia que
produce valores positivos invertidos en bits (GoogleSQL o
PostgreSQL).
Cada secuencia mantiene un conjunto de contadores internos y los usa para generar un valor. El contador de secuencia proporciona la entrada al algoritmo de inversión de bits.
Cuando defines una columna con una expresión DEFAULT que usa la función GET_NEXT_SEQUENCE_VALUE de GoogleSQL o la función nextval de PostgreSQL como su valor predeterminado, Spanner llama automáticamente a la función y coloca los valores de salida invertidos en bits en la columna. Las secuencias invertidas en bits son especialmente útiles para las claves primarias, ya que los valores invertidos en bits se distribuyen de manera uniforme en el espacio de claves para que no causen hotspots.
En el siguiente ejemplo, se muestra cómo crear una secuencia invertida en bits y una tabla en la que su columna clave usa la secuencia como valor predeterminado:
GoogleSQL
CREATE SEQUENCE SingerIdSequence OPTIONS (
sequence_kind="bit_reversed_positive"
);
CREATE TABLE Singers (
SingerId INT64 DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE SingerIdSequence)),
Name STRING(MAX),
Rank INT64
) PRIMARY KEY (SingerId);
PostgreSQL
CREATE SEQUENCE SingerIdSequence bit_reversed_positive;
CREATE TABLE Singers (
SingerId bigint DEFAULT nextval('SingerIdSequence'),
Name text,
PRIMARY KEY (SingerId)
);
Luego, puedes usar la siguiente instrucción de SQL para insertar y mostrar el valor de la clave primaria:
GoogleSQL
INSERT INTO Singers (Name) VALUES ('Example Singer')
THEN RETURN SingerId;
PostgreSQL
INSERT INTO Singers (name) VALUES ('Example Singer')
RETURNING SingerId;
Esta instrucción muestra un resultado similar al siguiente:
| SingerId |
|---|
| 3458764513820540928 |
Crea una tabla sin definir una clave primaria
Si no proporcionas claves primarias cuando creas una tabla, Spanner crea una columna oculta llamada rowid. Esta columna sirve como clave primaria. De forma predeterminada, la columna rowid es una columna
IDENTITY
que usa valores INT64 y está respaldada por una
secuencia invertida en bits para generar claves
automáticamente.
Puedes crear una tabla sin definir claves primarias de la siguiente manera:
GoogleSQL
CREATE TABLE Singers (
Name STRING(MAX),
Rank INT64
);
PostgreSQL
CREATE TABLE Singers (
Name text,
Rank bigint
);
El esquema resultante se muestra de la siguiente manera:
GoogleSQL
CREATE TABLE Singers (
Name STRING(MAX),
Rank INT64,
rowid INT64 NOT NULL GENERATED BY DEFAULT AS IDENTITY
(BIT_REVERSED_POSITIVE) HIDDEN
) PRIMARY KEY (rowid);
PostgreSQL
CREATE TABLE Singers (
Name text,
Rank bigint,
rowid bigint GENERATED BY DEFAULT AS IDENTITY
(BIT_REVERSED_POSITIVE) NOT NULL HIDDEN,
PRIMARY KEY (rowid)
);
No puedes agregar una clave primaria a una tabla que creaste anteriormente sin definir una clave primaria.
Debido a que Spanner no permite dos columnas con el mismo nombre en una tabla, no puedes definir una nueva columna no clave llamada rowid en una tabla que creaste anteriormente sin definir claves primarias. La siguiente consulta muestra un error:
GoogleSQL
CREATE TABLE Singers (
rowid INT64,
Name STRING(MAX),
);
PostgreSQL
CREATE TABLE Singers (
rowid bigint,
Name text
);
Spanner establece la columna rowid en HIDDEN. Esto significa que la columna no aparece en una consulta SELECT *:
GoogleSQL
SELECT * FROM Singers;
/*-------+------+
| Name | Rank |
+-------+------+
| Alice | 1 |
| David | 2 |
+-------+------*/
PostgreSQL
SELECT * FROM Singers;
/*-------+------+
| Name | Rank |
+-------+------+
| Alice | 1 |
| David | 2 |
+-------+------*/
Sin embargo, puedes consultar explícitamente la columna rowid oculta:
GoogleSQL
SELECT rowid FROM Singers;
/*---------------------+
| rowid |
+---------------------+
| 3458764513820540928 |
+---------------------*/
PostgreSQL
SELECT rowid FROM Singers;
/*---------------------+
| rowid |
+---------------------+
| 3458764513820540928 |
+---------------------*/
Aunque la columna rowid no aparece en una consulta SELECT *, la columna rowid es visible en las tablas INFORMATION_SCHEMA. Por ejemplo, puedes ejecutar la siguiente consulta:
GoogleSQL
SELECT column_name
FROM information_schema.key_column_usage
WHERE constraint_name LIKE 'PK_%' AND table_name = 'Singers';
/*-------------+
| column_name |
+-------------+
| rowid |
+-------------*/
PostgreSQL
SELECT column_name
FROM information_schema.key_column_usage
WHERE constraint_name LIKE 'PK_%' AND table_name = 'singers';
/*-------------+
| column_name |
+-------------+
| "rowid" |
+-------------*/
Situaciones para usar UUID y secuencias como valores predeterminados para claves primarias
Las situaciones para UUID y secuencias incluyen lo siguiente:
- Aplicaciones nuevas
- Migraciones
En las siguientes secciones, se describe cada situación.
Aplicaciones nuevas
Para las aplicaciones nuevas, Spanner recomienda usar un identificador único universal (UUID) para las claves primarias. Para obtener más información, consulta Usa un identificador único universal (UUID).
Si tu aplicación existente requiere INT64 claves en GoogleSQL o
bigint claves en PostgreSQL, Spanner ofrece el
objeto de esquema de secuencia positiva invertida en bits (PostgreSQL o
GoogleSQL).
Migraciones
Para migrar tablas a Spanner, tienes las siguientes opciones:
- Si usas UUID en tu base de datos de origen, en Spanner, puedes usar una columna de tipo UUID y la función UUID generada ( GoogleSQL o PostgreSQL) como su valor predeterminado.
- Si usas una clave primaria de números enteros y tu aplicación solo necesita que la clave sea única, puedes usar una columna clave en
INT64y usar una secuencia positiva invertida en bits para el valor predeterminado de la clave primaria. Consulta Cómo migrar columnas clave invertidas en bits. - Si usas una clave monotónica, como el tipo
SERIALde PostgreSQL o el atributoAUTO_INCREMENTde MySQL, y necesitas claves monotónicas nuevas en Spanner, puedes usar una clave compuesta porque Spanner no admite una forma de generar valores monotónicos. Para obtener más información, consulta Cómo intercambiar el orden de las claves y Cómo generar un hash de la clave única y distribuir las escrituras en fragmentos lógicos. - Si tu aplicación invierte manualmente en bits tu clave
INT64en GoogleSQL o tu clavebiginten PostgreSQL, puedes usar una secuencia positiva invertida en bits (GoogleSQL o PostgreSQL) y hacer que genere nuevos valores clave por ti. Para obtener más información, consulta Cómo migrar columnas clave invertidas en bits.
¿Qué sigue?
- Obtén más información para usar secuencias con control de acceso detallado.
- Obtén información sobre las sentencias DDL
SEQUENCEpara GoogleSQL o PostgreSQL. - Obtén información sobre las funciones de secuencia en GoogleSQL o PostgreSQL.
- Obtén información sobre las secuencias en el
INFORMATION_SCHEMAen GoogleSQL o PostgreSQL. - Obtén información sobre las opciones de secuencia en el
INFORMATION_SCHEMApara GoogleSQL.