¿Cuánto hay de nuevo en la Docena del Diablo?

Estamos hablando solo de PostgreSQL 13. El 8 de abril tuvo lugar un "congelamiento": congelamiento de funciones de PostgreSQL , ahora solo se incluirán en esta versión las funciones que se aceptan antes de esta fecha.

Es difícil nombrar una versión revolucionaria de esto. No hay cambios cardinales, conceptuales en él. Además, parches tan importantes como Tabla y Funciones para el estándar JSON / SQL, que quería ver en PG12 junto al parche JSONPath, no tuvieron tiempo de ingresarlo; el almacenamiento integrado listo para usar no apareció, solo se está finalizando la interfaz. Pero la lista de mejoras sigue siendo impresionante. Hemos preparado un resumen bastante completo de los parches incluidos en la Docena del Diablo.




Cambios a los comandos SQL


CREATE DATABASE ... LOCALE

Utilitiesinitdb,createdby el equipoCREATE COLLATIONtiene una configuraciónLOCALEque le permite especificar valores para la derechaLC_CTYPEyLC_COLLATE. Ahora apareció la misma oportunidad en el equipoCREATE DATABASE:

CREATE DATABASE db_koi8r TEMPLATE template0 
    ENCODING 'KOI8R' LOCALE 'ru_RU.KOI8R';

ALTERAR VISTA ... RENOMBRAR COLUMNA

El nombre de la columna en la vista ahora se puede cambiar con el comandoALTER VIEW. Anteriormente, esto requería volver a crear la vista.

Supongamos que olvidó darle un nombre a la columna:

CREATE VIEW uptime AS SELECT current_timestamp, current_timestamp - pg_postmaster_start_time();
SELECT * FROM uptime;

       current_timestamp       |    ?column?     
-------------------------------+-----------------
 2020-03-23 15:37:00.088824+03 | 04:18:24.897856

Se puede arreglar:

ALTER VIEW uptime RENAME COLUMN "?column?" TO uptime;
SELECT * FROM uptime;

       current_timestamp       |     uptime      
-------------------------------+-----------------
 2020-03-23 15:37:40.726516+03 | 04:19:05.535548


ALTER TABLE ... ALTER COLUMN ... DROP EXPRESSION

La columna generada de la tabla ahora se puede normalizar, es decir, eliminar la expresión para evaluarla:

CREATE TABLE payments (
    id integer PRIMARY KEY,
    amount numeric(18,2),
    income_tax numeric(18,2) GENERATED ALWAYS AS (amount*0.13) STORED
);
INSERT INTO payments(id, amount) VALUES(1, 42);
\d payments

                                     Table "public.payments"
   Column   |     Type      | Collation | Nullable |                   Default            
        
------------+---------------+-----------+----------+--------------------------------------
 id         | integer       |           | not null |
 amount     | numeric(18,2) |           |          |
 income_tax | numeric(18,2) |           |          | generated always as ((amount * 0.13))
 stored
Indexes:
    "payments_pkey" PRIMARY KEY, btree (id)

Posteriormente, decidieron que se debe establecer explícitamente el ingreso_tax. Eliminar la expresión:

ALTER TABLE payments ALTER COLUMN income_tax DROP EXPRESSION;
\d payments

                   Table "public.payments"
   Column   |     Type      | Collation | Nullable | Default
------------+---------------+-----------+----------+---------
 id         | integer       |           | not null |
 amount     | numeric(18,2) |           |          |
 income_tax | numeric(18,2) |           |          |
Indexes:
    "payments_pkey" PRIMARY KEY, btree (id)

Por supuesto, los datos existentes de la columna no han desaparecido:

SELECT * FROM payments;

 id | amount | income_tax
----+--------+------------
  1 |  42.00 |       5.46


DROP DATABASE ... FORCE
Si desea eliminar una base de datos sin esperar a que todos los usuarios se desconecten, puede usar la nueva opción deFORCEcomandoDROP DATABASE.

CREATE DATABASE db;

Conéctese a la nueva base de datos:

CREATE EXTENSION IF NOT EXISTS dblink;
SELECT dblink_connect('dbname=db');

 dblink_connect
----------------
 OK

Y ahora eliminaremos, interrumpiendo por la fuerza, también pg_terminate_backend, las conexiones abiertas:

DROP DATABASE db WITH (FORCE);

ALTERAR TIPO ... ESTABLECER ALMACENAMIENTO
El comandoALTER TYPEpermite que los tipos de datos básicos cambien varias propiedades, en particular, la estrategia de almacenamiento. Anteriormente, solo se podía configurar en un equipoCREATE TYPE.

Para la demostración, no crearemos un nuevo tipo base, sino que usaremos el existentetsquery. Pero primero, cree una base de datos separada y conéctese a ella:

CREATE DATABASE db;
\c db

Se utiliza una estrategia de almacenamiento para el tipo de datos tsquery plain, por lo que las columnas de tablas de este tipo obtienen la misma estrategia:

SELECT typname,typstorage FROM pg_type WHERE typname = 'tsquery';

 typname | typstorage
---------+------------
 tsquery | p

CREATE TABLE queries (query tsquery);
SELECT attname, attstorage FROM pg_attribute WHERE attrelid = 'queries'::regclass AND attname = 'query';

 attname | attstorage
---------+------------
 query   | p

Si necesita utilizar una estrategia diferente para nuevas tablas, puede cambiar el tipo base:

ALTER TYPE tsquery SET (storage=external);
SELECT typname,typstorage FROM pg_type WHERE typname = 'tsquery';

 typname | typstorage
---------+------------
 tsquery | e

El tipo de almacenamiento en las nuevas tablas también cambiará:

CREATE TABLE new_queries (query tsquery);
SELECT attname, attstorage FROM pg_attribute WHERE attrelid = 'new_queries'::regclass AND attname = 'query';

 attname | attstorage
---------+------------
 query   | e

Debe tenerse en cuenta que cambiar una estrategia que implica el uso de TOAST plainno se puede volver a cambiar a :

ALTER TYPE tsquery SET (storage=plain);

ERROR:  cannot change type's storage to PLAIN

Por lo tanto, los experimentos se llevaron a cabo en una base de datos separada, lo cual no es una pena eliminar.

ALTERAR ESTADÍSTICAS ... ESTABLECER ESTADÍSTICAS El

comando le CREATE STATISTICSpermite recopilar listas de los valores más comunes para combinaciones seleccionadas de columnas de tabla. El número de valores más comunes recopilados está determinado por el parámetro default_statistics_target. El valor para estadísticas específicas ahora se puede cambiar con el comando:

ALTER STATISTICS  SET STATISTICS _;

OBTENGA PRIMERO con la opción CON TIES
Como sabe, enSELECTlugar de especificar uncomando,LIMITpuede usar la sintaxis definida en el estándar SQL:

SELECT *
FROM (VALUES (1,'1.1'), (2,'2.1'), (2,'2.2'), (3,'3.1')) t(a,b)
ORDER BY a
FETCH FIRST 2 ROWS ONLY;

 a |  b  
---+-----
 1 | 1.1
 2 | 2.1
(2 rows)

Ahora es FETCHcompatible con la frase WITH TIES, que agrega a la salida todas las líneas "relacionadas" (líneas iguales a las ya seleccionadas, si solo se tiene en cuenta la condición de clasificación):

SELECT *
FROM (VALUES (1,'1.1'), (2,'2.1'), (2,'2.2'), (3,'3.1')) t(a,b)
ORDER BY a
FETCH FIRST 2 ROWS WITH TIES;

 a |  b  
---+-----
 1 | 1.1
 2 | 2.1
 2 | 2.2
(3 rows)

Funciones integradas y tipos de datos


get_random_uuid La
nueva funciónget_random_uuiddevuelve el valor de UUID de la versión 4 (valor aleatorio):

SELECT gen_random_uuid();

           gen_random_uuid            
--------------------------------------
 25e02793-80c0-438c-be07-c94b966c43ab

La función es útil para generar valores únicos de UUID en sistemas distribuidos.
Anteriormente, tenía que usar las bibliotecas uuid-ossp o pgcrypto.

min_scale y trim_scale para valores de tipo numérico

La función min_scaledetermina el número de dígitos significativos en la parte fraccionaria del número, y la función trim_scaledescarta ceros no significativos :

SELECT n, min_scale(n), trim_scale(n) FROM (VALUES(42.42000)) as t(n);

    n     | min_scale | trim_scale
----------+-----------+------------
 42.42000 |         2 |      42.42



Reposición de mcd y mcm en la sección de funciones matemáticas. Ahora puede encontrar rápidamente el divisor común más grande (gcm) y el múltiplo común más pequeño (lcm):

SELECT gcd(54,24), lcm(54,24);

 gcd | lcm
-----+-----
   6 | 216

Funciones agregadas min y max para el tipo pg_lsn Se han agregado funciones agregadas para el

tipo de datosyeso le permite realizar consultas del formulario:pg_lsnminmax

SELECT min(restart_lsn) FROM pg_replication_slots;
SELECT min(sent_lsn) FROM pg_stat_replication;

Verificación del modificador de tipo del valor de retorno de una función

En versiones anteriores, el modificador de tipo no se verificó por el valor de retorno de la función.

Supongamos que hay un tipo para almacenar unidades monetarias y una función que devuelve el monto del impuesto sobre la renta:

CREATE TYPE currency AS (
    amount numeric(18,2),
    code   text
);
CREATE FUNCTION income_tax(quantity currency) RETURNS currency
    AS 'SELECT quantity.amount * 0.13, quantity.code' LANGUAGE SQL;

Llamando a la función, esperamos obtener dos decimales, sin embargo, obtenemos cuatro. Incluso la conversión explícita después de una llamada de función no ayuda (tercera columna):

SELECT amount, code, amount::numeric(18,2)
FROM income_tax(ROW(42.42, ''))\gx

-[ RECORD 1 ]--
amount | 5.5146
code   | 
amount | 5.5146

En la versión 13, el resultado es correcto:

SELECT amount, code, amount::numeric(18,2)
FROM income_tax(ROW(42.42, ''))\gx

-[ RECORD 1 ]
amount | 5.51
code   | 
amount | 5.51

Los nombres localizados en to_date () y to_timestamp ()

Funcionesto_datetambiénto_timestampaprendieron a entender los nombres traducidos de los meses y días de la semana. Anteriormente, solo se podían usar nombres en inglés:

SELECT to_date(', 24  2020', 'TMDay, DD TMMonth YYYY');

  to_date   
------------
 2020-03-24

normalizar y ESTÁ NORMALIZADO

Para cumplir con el estándar SQL, la función normalizar () se ha agregado para normalizar la cadena Unicode y el predicado IS NORMALIZADO para verificar si la cadena está normalizada.

SELECT str, normalize(str, NFC) AS nfc,
       str IS NFC NORMALIZED AS is_nfc_normalized,
       normalize(str, NFKC) AS nfkc,
       str IS NFKC NORMALIZED AS is_nfkc_normalized
FROM (VALUES(U&'\0032\2075')) AS vals(str)\gx

-[ RECORD 1 ]------+---
str                | 2⁵
nfc                | 2⁵
is_nfc_normalized  | t
nfkc               | 25
is_nfkc_normalized | f

Lea más sobre los formularios de normalización de UNICODE.

Tipo Xid8 y función xid8_current () para números de transacción de 64 bits Se

agregó un nuevo tipo de datos xid8 para el número de transacción de 64 bits. Pero no, esto no significa que PostgreSQL cambió a transacciones de 64 bits: todo funciona exactamente como antes. Sin embargo, algunas funciones devuelven un nuevo tipo, por ejemplo, ahora se recomienda para su uso en lugar de las antiguas funciones pg_current_xact_id txid_current, que volvió INT8, y así sucesivamente. N.

Nuevos tipos de datos polimórficos familia anycompatible

tipos añadió anycompatible, anycompatiblearray, anycompatiblenonarray, anycompatiblerange. A diferencia de los tipos familiares anyelement, los nuevos tipos le permiten usar no exactamente lo mismo, sino tipos realmente compatibles.

En el siguiente ejemplo, la funciónmaximumcomo argumentos definidos como anycompatiblese pasan integery numeric. El valor de retorno se convierte en un valor común para estos dos tipos:

CREATE FUNCTION maximum(a anycompatible, b anycompatible) RETURNS anycompatible
	AS 'SELECT CASE WHEN a > b THEN a ELSE b END' LANGUAGE SQL;

SELECT f, pg_typeof(f) FROM maximum(42, 42.42) f;

   f   | pg_typeof
-------+-----------
 42.42 | numeric

Además, los tipos anycompatible- y any- son dos conjuntos independientes de tipos:

CREATE FUNCTION first_elems(a anyarray, b anycompatiblearray)
    RETURNS TABLE(a anyelement, b anycompatible) AS $$
        SELECT ROW(a[array_lower(a,1)], b[array_lower(b,1)]);
    $$ LANGUAGE sql;
SELECT first_elems(ARRAY[1,2,3], ARRAY['a','b','c']) AS str, 
       first_elems(ARRAY[1.1,2.2,3.3],ARRAY[true,false]) bool;

  str  |  bool   
-------+---------
 (1,a) | (1.1,t)

Lenguajes de procedimiento


Transformación para tipo bool en PL / Perl
Recientemente, TRANSFORMACIÓN de Ivan Panchenko (Postgres Professional) - se comprometió bool_plperl . Postgres pasa valores booleanos atoen PL / Perl comof, pero para Perl quefNO un valor booleano falso , pero sólo la letra f, es decir, en un contexto lógico, verdad . Este problema se puede resolver de diferentes maneras (ver correspondencia ), pero crear TRANSFORM para bool, según Tom Lane, es lo más práctico.

Ejecución rápida de expresiones simples en PL / pgSQL

Las expresiones simples (al menos que no contienen llamadas a la tabla y no requieren bloqueos) serán más rápidas. Anteriormente, en estos casos, se dedicaba tiempo improductivo a contactar al programador en cada ciclo.

CREATE OR REPLACE FUNCTION slow_pi() RETURNS double precision AS $$
    DECLARE
        a double precision := 1;
        s double precision := 1;
        r double precision := 0;
    BEGIN
        FOR i IN 1 .. 10000000 LOOP
            r := r + s/a; a := a + 2; s := -s;
        END LOOP;
        RETURN 4*r;
    END;
    $$ LANGUAGE plpgsql;

Llame slow_pi () en PG12:

SELECT slow_pi();

          slow_pi      
    --------------------
     3.1415925535898497
    (1 row)
    Time: 13060,650 ms (00:13,061)

Ahora en PG13:
SELECT slow_pi();

          slow_pi      
    --------------------
     3.1415925535897915
    (1 row)
    Time: 2108,464 ms (00:02,108)

Extensiones de confianza en lugar de pg_pltemplate

El directorio del sistema ha disminuido en una tabla. Borradopg_pltemplate. Almacenaba las propiedades de los lenguajes de procedimiento que se necesitan durante la ejecuciónCREATE LANGUAGE. Ahora decidimos registrar las propiedades en los scripts de las extensiones de los idiomas correspondientespg_pltemplatey deshacernos de la tabla en sí. Pero para implementar el plan, es necesario proporcionar la posibilidad para que el propietario de la base de datos (sin derechos de superusuario) cree un lenguaje confiable a partir del script de extensión. De hecho, ahora para crear, por ejemplo, plpgsql, el propietario de la base de datos no tiene que ser superusuario.

Recibido de la siguiente manera. Ha aparecido un nuevo parámetro lógico en el archivo de control para extensionestrusted. Si ambos parámetrostrustedysuperuserincluida, entonces la extensión puede ser creada no solo por el superusuario, sino también por el usuario con derecho CREATEa la base de datos actual (y, por lo tanto, a su propietario). Al ejecutar un script de dicha extensión, se utilizarán los derechos de superusuario que inicializaron el clúster. Los objetos creados por la extensión le pertenecerán, aunque el propietario de la extensión en sí será el usuario creador.

Consecuencias importantes de estos cambios:

  • Las extensiones confiables abren el camino para que los desarrolladores externos creen otros idiomas confiables. Ahora estamos limitados solo a plpgsql, plperl y pltcl.
  • Fue pg_pltemplateescrito que plpython se refiere a la segunda versión del lenguaje. No pg_pltemplatehacerlo es un paso (necesario, aunque no suficiente) para la transición a Python 3.

Índices


Compresión del árbol B
Un parche importante y muy esperado (el trabajo comenzó ya en 2015) escrito por Anastasia Lubennikova (Postgres Professional) y Peter Geigan (Peter Geoghegan) finalmente se comunica por Peter. Nastya logró hablar de esto en PGconf India . Postgres ha aprendido a reducir significativamente el tamaño de los índices del árbol B a través de la deduplicación, es decir, ahorros en claves de índice duplicadas. Estos índices se han rediseñado seriamente para que la compresión sea posible sin pérdida de compatibilidad con versiones anteriores de índices. La idea de la deduplicación se toma de una arquitectura más flexible de índices como GIN (índices inversos - Índice invertido generalizado).

En estos índices con mayor frecuencia que en el árbol B, existe una situación en la que una clave corresponde a una gran cantidad de registros. En el caso del procesamiento de textos, por ejemplo, el mismo token se encuentra generalmente en varios documentos. Y se almacena en el índice solo una vez. Hasta hace poco, los índices del árbol B no sabían cómo hacer esto.

Los índices del árbol B difieren de los índices GIN principalmente en las páginas de hoja. Dependiendo del número de registros relacionados con el mismo valor clave, las opciones son posibles: la página contiene solo una lista de publicación: una lista de TID (identificadores de registros indexados), si la lista es pequeña y si hay muchos TID, en lugar de una lista de valores se almacenan Nuevas "ramas de árbol": enlaces a otras páginas como la lista de publicaciones u otras ramas de árbol (se llaman árbol de publicación).

Tal estructura de árbol es similar a un árbol B, pero difiere en detalles esenciales: por ejemplo, las listas para moverse a través de páginas del mismo nivel de árbol en el GIN son unidireccionales, no bidireccionales. Por lo tanto (incluida) una buena compatibilidad de índices nuevos y deduplicados con versiones antiguas no es fácil de lograr. Y las mejoras realmente tomaron más de 3 años. También fue necesario resolver el mecanismo de limpieza (microvacío) y otros matices.

En las pruebas de rendimiento, todos los índices a los que se aplica la deduplicación se han reducido aproximadamente 3 veces. La compresión de duplicados también ayuda a índices únicos, eliminando el problema de la hinchazón del índice a una alta tasa de cambios en la tabla. Se puede conectar y desconectar un nuevo comportamiento en el nivel de configuración del índice.

El escaneo completo por índice GIN no se realiza donde no es necesario
Este parche permite en algunos casos evitar un pase completo a través de todo el índice GIN. Algunas operaciones, aunque son compatibles con el índice GIN, se realizan mediante un análisis completo del índice. Tomemos, por ejemplo, el índice para la búsqueda de columna de texto completo tsvector. Si la consulta de búsqueda tiene la forma "cualquier cosa menos una palabra dada", entonces todo el índice deberá leerse en su totalidad. Sin embargo, si hay otra condición presente en la solicitud que no requiere un escaneo completo del índice, entonces el índice aún se escaneará por completo.

Con la nueva optimización, se usará primero una condición más precisa, que le permitirá obtener una ganancia del índice, y luego los resultados se verificarán dos veces para tener en cuenta otra limitación. Compare el número de páginas que se leyeron en la versión 12 (Buffers):

EXPLAIN (ANALYZE, BUFFERS, COSTS OFF, TIMING OFF)
SELECT * FROM mail_messages WHERE tsv @@ to_tsquery('!vacuum') AND tsv @@ to_tsquery('analyze');

                                             QUERY PLAN                                             
------------------------------------------------------------------
Bitmap Heap Scan on mail_messages (actual rows=5864 loops=1)
   Recheck Cond: ((tsv @@ to_tsquery('!vacuum'::text)) AND (tsv @@ to_tsquery('analyze'::text)))
   Heap Blocks: exact=5167
   Buffers: shared hit=24 read=27405
   ->  Bitmap Index Scan on mail_messages_tsv_idx (actual rows=5864 loops=1)
         Index Cond: ((tsv @@ to_tsquery('!vacuum'::text)) AND (tsv @@ to_tsquery('analyze'::text)))
         Buffers: shared hit=24 read=22238
 Planning Time: 0.283 ms
 Execution Time: 3258.234 ms

con el número de buffers en la nueva versión:

EXPLAIN (ANALYZE, BUFFERS, COSTS OFF, TIMING OFF)
SELECT * FROM mail_messages WHERE tsv @@ to_tsquery('!vacuum') AND tsv @@ to_tsquery('analyze');

                                             QUERY PLAN                                             
---------------------------------------------------------------------------
Bitmap Heap Scan on mail_messages (actual rows=5864 loops=1)
   Recheck Cond: ((tsv @@ to_tsquery('!vacuum'::text)) AND (tsv @@ to_tsquery('analyze'::text)))
   Heap Blocks: exact=5156
   Buffers: shared hit=5179
   ->  Bitmap Index Scan on mail_messages_tsv_idx (actual rows=5864 loops=1)
         Index Cond: ((tsv @@ to_tsquery('!vacuum'::text)) AND (tsv @@ to_tsquery('analyze'::text)))
         Buffers: shared hit=23
 Planning Time: 0.250 ms
 Execution Time: 8.779 ms

Se puede encontrar una situación similar al usar trigramas y al verificar la aparición de matrices.

Parámetros de las clases de operador
En PostgreSQL, muchos métodos de acceso al índice son un "marco" que adopta una implementación de alto nivel del algoritmo de búsqueda, trabajando con páginas y bloqueos, y el registro WAL. Y el enlace a tipos de datos y operadores específicos se realiza mediante clases de operador.

Hasta ahora, las clases de operador no podían tener parámetros. Por ejemplo, para una búsqueda de texto completo, se puede usar un índice GiST con una clase de operadores tsvector_ops(sobre las clases de operadores GiST aquí) Esta clase de operadores utiliza un árbol de firma, y ​​la longitud de la firma fue fija (124 bytes). Ahora puede especificar la longitud explícitamente, lo que le permite controlar el equilibrio entre el tamaño del índice y la eficiencia (el número de colisiones hash):

CREATE INDEX ON mail_messages USING gist(tsv tsvector_ops(siglen=1024));

Se realizaron cambios similares para los iniciadores para otras clases de operadores GiST que usan un árbol de firma, que se aplica a las extensiones hstore, intarray, ltree y pg_trgm.
Pero la idea principal para la que se concibió este cambio es la capacidad de pasar la expresión JSONPath al índice GIN para que no se indexe todo el documento JSON, sino solo la parte necesaria. En muchos casos, esto reducirá radicalmente el tamaño de los índices. Pero este trabajo queda por hacer.

La idea de Oleg Bartunov, la implementación de Nikita Glukhov y Alexander Korotkov (los tres profesionales de Postgres).

Se
agregó el operador <-> (recuadro, punto) . La operación faltante se agregó para usar en kNN para GiST y SP-GiST . En PG12 cuando se trabaja con tipos geométricos pointyboxpuede usar el operador de distancia <->(point, box), y acelerará la búsqueda con los índices GiST y SP-GiST. Pero el operador simétrico para él <->(box, point)no se implementó, aunque boxya entendía las distancias a tipos más complejos: polígonos y círculos.

CREATE TABLE points(point point);
CREATE TABLE boxes(box box);
INSERT INTO points VALUES('1,2','3,4');
INSERT INTO boxes VALUES(box(point(3,4),point(5,6)), box(point(13,14),point(15,16)));

En PG12:
SELECT p.point, b.box, b.box  <-> p.point distance FROM points AS p, boxes AS b ORDER BY distance;

:    : box <-> point

Si viceversa, entonces todo está bien:

SELECT p.point, b.box, p.point  <-> b.box distance FROM points AS p, boxes AS b ORDER BY distance;

 point |       box       |      distance
-------+-----------------+--------------------
 (1,2) | (5,6),(3,4)     | 2.8284271247461903
 (2,1) | (5,6),(3,4)     | 3.1622776601683795
 (1,2) | (15,16),(13,14) | 16.970562748477143
 (2,1) | (15,16),(13,14) | 17.029386365926403

Y en PG13:

SELECT p.point, b.box, b.box  <-> p.point distance FROM points AS p, boxes AS b ORDER BY distance;

 point |       box       |      distance
-------+-----------------+--------------------
 (1,2) | (5,6),(3,4)     | 2.8284271247461903
 (2,1) | (5,6),(3,4)     | 3.1622776601683795
 (1,2) | (15,16),(13,14) | 16.970562748477143
 (2,1) | (15,16),(13,14) | 17.029386365926403

Los índices GiST y SP-GiST se acelerarán en esta operación.

Tenga en cuenta que en PG13, si pregunta:

SELECT count(*) FROM pg_operator WHERE oprname = '<->';
 count 
-------
    28

y si hacemos lo mismo en PG12, obtenemos 20 entradas: en la 13ª versión, la lista se repone con hasta 8 operadores.

Json


Soporte para el método .datetime () para jsonpath

Este es uno de los parches fallidos de una gran serie de parches JSONPath que PG12 no tuvo tiempo de completar. Parte del estándar JSON / SQL. El problema era que todas las funciones de la serie de parches JSONPath son inmutables, pero la comparación de fechas tiene en cuenta la zona horaria actual, que puede cambiar durante la sesión.

En tales casos, permitimos que las funciones inmutables existentes arrojen un error sobre comparaciones no inmutables. Al mismo tiempo, este parche tiene funciones con el sufijo _tz que funcionan de manera estable en operaciones con zona horaria.

Nueva función: función jsonb_set_lax

En general, lax es un modo de operación no estricto (a diferencia de estricto) de las funciones con jsonb. En este caso, esta función estará operativa en una situación en la que uno de los argumentos que toma es NULL. A diferencia de la versión estricta, jsonb_set (), tiene un argumento adicional que indica acciones en el caso de NULL. Opciones: use_json_null / raise_exception / return_target / delete_key. Opciones sugeridas por los usuarios interesados.

Optimizado algunas funciones jsonb.

Optimizado mucho., principalmente a través de los esfuerzos de Nikita Glukhov (Postgres Professional). Pero analizar cada punto en este caso no tiene sentido: en primer lugar, su abundancia inflará un artículo ya corto; y en segundo lugar, los cambios se relacionan con el dispositivo interno y no todos los usuarios están interesados. Por lo tanto, solo enumeraremos la mayoría de ellos:

  1. Función optimizada JsonbExtractScalar ();
  2. Operador optimizado # >>, funciones jsonb_each_text (), jsonb_array_elements_text ();
  3. El reconocimiento del tipo JsonbContainer en get_jsonb_path_all () está optimizado;
  4. Obtener el primer token del iterador JsonbIterator se reemplaza por la macro ligera JsonbContainerIsXxx ();
  5. Extracción de claves más conveniente: findJsonbKeyInObject ();
  6. Almacenamiento optimizado del resultado findJsonbValueFromContainer () y getIthJsonbValueFromContainer ();
  7. get_jsonb_path_all(), ;
    JsonbValueAsText.

, SQL/JSON: JSON_TABLE SQL/JSON: functions. . , . . PG14. JSONPath .


pgbench


La utilidad para ejecutar pruebas de rendimiento recibió una serie de mejoras. Había estadísticas sobre la ejecución de tareas en la fase de inicialización, una conclusión más visual , la capacidad de ver el código de los scripts incorporados , las pruebas en una tabla de cuentas particionada .

Además, agregamos un comando \asetsimilar a \gset, pero que permite establecer valores para variables de varias solicitudes enviadas a la vez. La siguiente línea, enviada al servidor para su ejecución, establece ambas variables oney two:
SELECT 1 AS one \; SELECT 2 AS two \aset

pg_dump


pg_dump aprendió a descargar datos de tablas de terceros . A través del parámetro, --include-foreign-datapuede especificar una lista de servidores de terceros, cuyos datos de las tablas se descargarán.

Use esta descarga con cuidado. Lejos del hecho de que los datos deben cargarse en un servidor de terceros. Además, es muy posible que un servidor de terceros no esté disponible durante la recuperación. O un servidor de terceros solo puede permitir leer, pero no escribir datos.

psql


Una serie de pequeños parches hace que psql sea más cómodo:

  • Mejora de la finalización de pestañas para varios equipos.
  • Además de \echoenviar una cadena a STDOUT, un nuevo comando \warnenvía una cadena a la salida de error estándar (STDERR).
  • \d toast- . \d+ .
  • \dt+ «Persistence» (unlogged) (permanent).
  • \e , ; ( \g*). , psql .
  • . PROMPT1 PROMPT2 %x.
  • Los nuevos comandos para obtener más información sobre los métodos de acceso: \dAc, \dAf, \dAo,\dAp
  • Usted puede\g ahora especificar entre corchetes las opciones que son compatibles \pset. Actuarán solo en el equipo actual.


libpq


Cambios menores en conexión con PostgreSQL:
  • Se corrigió la inexactitud en la descripción de los parámetros host y hostadr y la inconsistencia resultante en la salida del \conninfocomando de utilidad psql.
  • Si la clave del certificado del cliente se almacena en forma cifrada, puede ingresar la contraseña solo en modo interactivo. El nuevo parámetro sslpassword le permite descifrar la clave de forma no interactiva.
  • Dos nuevos parámetros, sslminprotocolversion y sslmaxprotocolversion, le permiten especificar una restricción en la versión del protocolo SSL / TCL con el que se permite la conexión.

reindexdb


El nuevo parámetro --jobs de la utilidad reindexdb establece el número de conexiones de bases de datos en las que los índices se reconstruirán al mismo tiempo.

pg_rewind


Las limitaciones de la utilidad se eliminan gradualmente y las posibilidades aumentan.
En primer lugar, pg_rewind ahora puede registrar información para la recuperación (como pg_basebackup puede hacer esto), así como iniciar la recuperación y el cierre posterior de una instancia si no se detuvo a través de un punto de control (esto tenía que hacerse manualmente antes).

Y en segundo lugar, pg_rewind aprendió a trabajar con el archivo WAL .
Una vez que la utilidad encuentra el punto de divergencia WAL entre los dos servidores, debe crear una lista de todas las páginas que deben copiarse en el clúster de destino para eliminar las diferencias. Para esto, la utilidad requiere todos los archivos WAL, comenzando desde el punto encontrado. Si los archivos WAL necesarios no están disponibles en el clúster de destino, la utilidad no podría realizar su trabajo antes.

Con este parche de Alexey Kondratov (Postgres Professional), pg_rewind podrá leer los segmentos WAL faltantes del archivo de los archivos de registro utilizando el parámetro restore_command si se especifica un nuevo modificador -c o --restore-target-wal.

pg_waldump


pg_waldump descifrará el registro de transacción preparado.

amcheck


La extensión amcheck ha aprendido a reconocer mejor el daño en los índices del árbol B.
Por cierto, ahora los mensajes en el registro del servidor sobre páginas dañadas serán diferentes para los índices y las tablas .

inspeccion de pagina


La heap_tuple_infomask_flagsfunción de extensión pageinspect descifra los valores de los campos infomask y los infomask2devuelve la función heap_page_items. Útil en la investigación de situaciones de corrupción de datos.

postgres_fdw


El superusuario en el nivel de asignación de nombre de usuario puede permitir a los usuarios normales utilizar una conexión sin contraseña:

ALTER USER MAPPING FOR  SERVER 
    OPTIONS (ADD password_required 'false');

Esto se hace, entre otras cosas, para que sslkey y sslcert puedan usarse como parámetros de conexión .

adminpack


La extensión adminpack tiene una nueva característica - pg_file_sync. Utilizándolo, puede hacer fsync para archivos escritos por el servidor en el disco, por ejemplo, a través de pg_file_writeo COPY TO.

Supervisión


pg_stat_slru


En la memoria compartida del servidor, no solo hay una gran memoria caché de búfer, sino también varias otras memorias caché más simples (por ejemplo, para el estado de la transacción). Utilizan un algoritmo simple para desplazar las páginas que se usan con menos frecuencia (simples, menos utilizadas recientemente o SLRU). Hasta ahora, tales cachés "simplemente funcionaban", pero era necesario monitorearlos, en primer lugar para que los desarrolladores del kernel de PostgreSQL descubrieran si es necesario cambiar algo en ellos. Para este y propósito, ha aparecido una nueva vista de pg_stat_slru .

pg_stat_activity


En la vista, la pg_stat_activity nueva columna es leader_id. Para los procesos que participan en solicitudes paralelas, se rellena con el número del proceso principal. Y el proceso principal leader_ides un número de proceso pid.
La siguiente consulta muestra qué consultas y qué procesos se ejecutan actualmente en paralelo:

SELECT query, leader_pid, 
    array_agg(pid) filter(WHERE leader_pid != pid) AS members
  FROM pg_stat_activity
 WHERE leader_pid IS NOT NULL
 GROUP BY query, leader_pid;

Hay cambios en la lista de eventos en espera. Se agregaron dos nuevos eventos : BackupWaitWalArchivey RecoveryPause. Y los otros dos recibieron nombres más precisos: RecoveryWalStream -> RecoveryRetrieveRetryInterval, RecoveryWalAll -> RecoveryWalStream.

Y dos nuevos eventos de espera nuevos que ocurren en la réplica : RecoveryConflictSnapshot(conflicto con VACUUM, que eliminó la versión necesaria de las filas) y RecoveryConflictTablespace(conflicto relacionado con la eliminación del espacio de tablas).

pg_stat_statements


Hasta ahora, la extensión ha pg_stat_statementstratado las solicitudes con FOR UPDATEy sin una frase como la misma solicitud. Ahora las solicitudes con FOR UPDATE se registran por separado .

La cantidad de información recopilada ha aumentado. De ahora en adelante, no solo se registra información sobre recursos para ejecutar comandos, sino también estadísticas sobre entradas de diario generadas . Nuevas columnas de presentación: wal_bytes- volumen de registros generados, wal_records- número de registros generados, wal_num_fpw- número de imágenes de página completa (escrituras de página completa).

Esto fue posible gracias a la infraestructura preparada para rastrear el uso de WAL. Por lo tanto, ahora EXPLAINcon una nueva opción WAL, mostrará el volumen de registros generados:

CREATE TABLE t (id int);
EXPLAIN (ANALYZE, WAL, COSTS OFF, TIMING OFF, SUMMARY OFF)
    INSERT INTO t VALUES(1);

              QUERY PLAN              
--------------------------------------
 Insert on t (actual rows=0 loops=1)
   WAL:  records=1  bytes=59
   ->  Result (actual rows=1 loops=1)

Extension auto_explain, VACUUMs VERBOSE, y autovacuumtambién utilizan la infraestructura creada y generarán volúmenes de WAL.

Volviendo a pg_stat_statements. Si el nuevo parámetro pg_stat_statements.track_planning está habilitado , se registrarán estadísticas adicionales relacionadas con el planificador para cada operador: número de compilaciones del plan; tiempo total de planificación; tiempo mínimo y máximo de una planificación, así como desviación media y estándar.

La contabilidad de los recursos asignados al planificador se refleja en otro parche que no está relacionado pg_stat_statements. EXPLAINcon la opción BUFFERSinformará el número de buffers utilizados en la etapa de planificación :

EXPLAIN (ANALYZE, BUFFERS, COSTS OFF, TIMING OFF) 
    SELECT * FROM pg_class;

                   QUERY PLAN                   
------------------------------------------------
 Seq Scan on pg_class (actual rows=386 loops=1)
   Buffers: shared hit=9 read=4
 Planning Time: 0.782 ms
   Buffers: shared hit=103 read=11
 Execution Time: 0.219 ms

Revista


  • log_statement_sample_rate SQL, , log_min_duration_sample( ).
    , log_min_duration_statement , .. log_min_duration_statement , log_min_duration_sample, , log_statement_sample_rate.
    , log_transaction_sample_rate , , .
  • , ( log_min_error_statement), . log_parameter_max_length_on_error. 0, .
    log_parameter_max_length_on_error SQL, , .
    ( log_statements log_duration) , : log_parameter_max_length, , .
  • Ahora puede escribir el tipo de proceso ( pg_stat_activity.backend_type) en el registro del servidor . Para esto log_line_prefix, se proporciona un símbolo especial en el parámetro %b. Y si el registro está escrito en formato csv ( log_destination=csvlog), entonces la columna backend_typeya está incluida allí.


Progreso


Las nuevas vistas pg_stat_progress_analyzetambién le pg_stat_progress_basebackuppermiten realizar un seguimiento del progreso de la recopilación de estadísticas por parte del equipo ANALYZEy crear una copia de seguridad de la utilidad, pg_basebackuprespectivamente.

Mejoramiento


Cálculo de funciones inmutables en la cláusula FROM en la etapa de planificación
El parche de Aleksandr Kuzmenkov y Aleksandr Parfyonov (ambos de Postgres Professional) ayuda en los casos en que laFROMllamada contiene una llamada de función que en realidad es una constante. En este caso, en lugar de hacer la conexión, el valor constante se sustituye en los lugares necesarios de la solicitud.

Así es como sucede esto con un ejemplo de una consulta relacionada con la búsqueda de texto completo:

EXPLAIN (COSTS OFF)
SELECT subject, ts_rank_cd(tsv, q) AS rank
FROM mail_messages, to_tsquery('english', 'tuple') q
WHERE tsv @@ q
ORDER BY rank DESC;

                              QUERY PLAN                              
------------------------------------------------------------------
 Sort
   Sort Key: (ts_rank_cd(mail_messages.tsv, '''tuple'''::tsquery)) DESC
   ->  Bitmap Heap Scan on mail_messages
         Recheck Cond: (tsv @@ '''tuple'''::tsquery)
         ->  Bitmap Index Scan on mail_messages_tsv_idx
               Index Cond: (tsv @@ '''tuple'''::tsquery)

No hay conexión, y el valor 'tupla' :: tsquery se sustituye en la consulta ya en la etapa de planificación. La versión 12 tenía una imagen completamente diferente:

EXPLAIN (COSTS OFF)
SELECT subject, ts_rank_cd(tsv, q) AS rank                            
FROM mail_messages, to_tsquery('english', 'tuple') q
WHERE tsv @@ q                            
ORDER BY rank DESC;

                          QUERY PLAN                         
-----------------------------------------------------
 Sort
   Sort Key: (ts_rank_cd(mail_messages.tsv, q.q)) DESC
   ->  Nested Loop
         ->  Function Scan on q
         ->  Bitmap Heap Scan on mail_messages
               Recheck Cond: (tsv @@ q.q)
               ->  Bitmap Index Scan on mail_messages_tsv_idx
                     Index Cond: (tsv @@ q.q)


Clasificación incremental

Cuando se necesita ordenar por muchas claves (k1, k2, k3 ...), el planificador ahora puede aprovechar el conocimiento de que los datos ya están ordenados por varias de las primeras claves (por ejemplo, k1 y k2). En este caso, no puede volver a ordenar todos los datos nuevamente, sino dividirlos en grupos consecutivos con los mismos valores k1 y k2, y "ordenar" por la clave k3.

Por lo tanto, toda la clasificación se divide en varios tipos consecutivos de menor tamaño. Esto reduce la cantidad de memoria necesaria y también le permite entregar los primeros datos antes de que se complete toda la clasificación.

Por ejemplo, en la base de datos de demostración en la tabla de tickets hay un índice en la columna ticket_id. Los datos recibidos del índice se ordenarán por ticket_id, por lo que la siguiente consulta utilizará una ordenación incremental:

EXPLAIN (analyze, costs off, timing off)
SELECT * FROM tickets ORDER BY ticket_no, passenger_id;

                                  QUERY PLAN                                  
------------------------------------------------------------------------------
 Incremental Sort (actual rows=2949857 loops=1)
   Sort Key: ticket_no, passenger_id
   Presorted Key: ticket_no
   Full-sort Groups: 92184 Sort Method: quicksort Memory: avg=31kB peak=31kB
   ->  Index Scan using tickets_pkey on tickets (actual rows=2949857 loops=1)
 Planning Time: 2.137 ms
 Execution Time: 2230.019 ms

La funcionalidad de ordenación incremental se puede deshabilitar con el parámetro enable_incrementalsort. En este caso, la clasificación llevará mucho más tiempo:

SET enable_incrementalsort = off;
EXPLAIN (analyze, costs off, timing off)
SELECT * FROM tickets ORDER BY ticket_no, passenger_id;

                              QUERY PLAN                               
-----------------------------------------------------------------------
 Gather Merge (actual rows=2949857 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   ->  Sort (actual rows=983286 loops=3)
         Sort Key: ticket_no, passenger_id
         Sort Method: external merge  Disk: 107024kB
         Worker 0:  Sort Method: external merge  Disk: 116744kB
         Worker 1:  Sort Method: external merge  Disk: 107200kB
         ->  Parallel Seq Scan on tickets (actual rows=983286 loops=3)
 Planning Time: 3.994 ms
 Execution Time: 12291.844 ms

La idea de la clasificación incremental fue propuesta en 2013 por Alexander Korotkov (Postgres Professional), y ahora, siete años después, James Coleman llevó el parche a un estado aceptado por la comunidad.

Aceleración TRUNCATE
Cuando se realiza el TRUNCATEescaneo shared_bufferspara eliminar los búferes de tabla de la memoria compartida. Anteriormente, el escaneo se realizaba tres veces, para cada capa de tabla: PRINCIPAL (capa de datos principal), FSM (mapa de espacio libre), VM (mapa de visibilidad). Ahora la lógica ha cambiado, en lugar de la operación triple, los buffers se escanean solo una vez. Con valores grandes, shared_buffersesto proporciona una ganancia tangible.

Tostada de descompresión parcial
Cuando no hay necesidad de leer completamente TOAST, limitándolo a una rebanada al principio o cerca del principio, entonces no tiene sentido desabrocharlo por completo. TOAST comprimido se lee en iteraciones: lea una pieza, si no hay datos necesarios, luego amplíela y siga leyendo. Sugerido por un estudiante de Google Summer of Code, Binguo Bao, que da un ejemplo:

CREATE TABLE slicingtest (
     id serial PRIMARY KEY,
     a text
);
INSERT INTO slicingtest (a) SELECT
    repeat('1234567890-=abcdefghijklmnopqrstuvwxyz', 1000000) AS a FROM
    generate_series(1,100);
\timing
SELECT sum(length(substr(a, 0, 20))) FROM slicingtest;

Time: 28.123 ms

Con el parche, un orden de magnitud más rápido:

Time: 2.306 ms

VACÍO Paralelo
En su artículo sobre este tema, Yegor Rogov explica en detalle este importante paso en la paralelización. En resumen: "Parche Masahiko Sawada, que le permite realizar la limpieza en paralelo. La tabla misma todavía se borra mediante un proceso (principal), pero para limpiar índices, ahora puede iniciar flujos de trabajo en segundo plano, uno para cada índice. En modo manual, esto le permite acelerar la limpieza de tablas grandes con múltiples índices; la limpieza automática aún no utiliza esta función ".

Limpieza automática cuando se pega en una mesa
Para este parche (también conocido como aspiradora automática Berserk), debemos agradecer a Dorofei Proleskovsky, quien propuso una solución al siguiente problema: la limpieza automática no llega a la tabla de solo agregar, porque no tienen versiones "muertas" de las filas. Debido a esto, el mapa de visibilidad no se actualiza, lo que hace que solo los escaneos de índice sean ineficaces, y cuando la limpieza llega a evitar desbordamientos del contador de transacciones, debe hacer mucho trabajo a la vez. Ahora esta situación se ha solucionado: la limpieza automática también funcionará para agregar líneas. Aparecieron dos nuevos parámetros del servidor ( autovacuum_vacuum_insert_thresholdy autovacuum_vacuum_insert_scale_factor), similares a los de las modificaciones ( autovacuum_vacuum_thresholdy autovacuum_vacuum_scale_factor).

Gestión de memoria agregada de hash
La agregación de hash puede requerir más RAM de la que pensaba el planificador y de lo indicado en work_mem. Anteriormente, dicho error del planificador conducía al hecho de que el tamaño se work_memignoraba y la memoria se asignaba tanto como fuera necesario para la operación o la llegada de OOM Killer. Ahora el algoritmo puede no ir más allá work_memy, si es necesario, usar archivos temporales en el disco. Para controlar el comportamiento del planificador, aparecieron los siguientes parámetros: enable_groupingsets_hash_disky enable_hashagg_disk.

Optimización de ACTUALIZACIÓN para tablas con columnas generadas
En la versión 12, las columnas generadas se recalculaban durante cualquier actualización de fila, incluso si este cambio no las afectaba de ninguna manera. Ahora serán recalculados solo cuando sea realmente necesario (si sus columnas base han cambiado).

Esta optimización, por ejemplo, puede acelerar significativamente la actualización de tablas con una columna de tipo generado tsvector, ya que la función es to_tsvector()bastante costosa.

Acceso desde el disparador a la lista de columnas modificadas
Un pequeño parche que agrega un TriggerDatamapa de bits de columnas modificadas a la estructura . Esta información puede ser utilizada por funciones de activación generales, como tsvector_update_trigger()o lo_manage(), para no realizar un trabajo innecesario.

Uso de varias estadísticas avanzadas al evaluar
En PG12, el planificador no pudo utilizar varias estadísticas avanzadas para la misma tabla al mismo tiempo. Por ejemplo, imagine una situación en la que se construyen dos estadísticas avanzadas para diferentes conjuntos de columnas, y las columnas de un conjunto y de otro participan en la consulta. Ahora el planificador tiene acceso a toda la información disponible.

Infraestructura para paralelización y COPIA (consulte también este parche ) .
La concurrencia de PostgreSQL todavía funciona para consultas de solo lectura. Hay dificultades con los escritores, y uno de ellos es el bloqueo de procesos que realizan simultáneamente una tarea (incluida en un grupo paralelo común). Se cree que los bloqueos de tales procesos no entran en conflicto; por ejemplo, varios procesos pueden mantener un bloqueo exclusivo en la misma tabla. Esto requiere un cuidado especial por parte de los desarrolladores del kernel, pero de lo contrario tendrían puntos muertos constantemente.
Pero hay dos excepciones:

  • bloqueo de extensión de relación, que se captura cuando se agregan nuevas páginas al final del archivo de datos, y
  • bloqueo de página, que se utiliza al mover elementos de índice GIN de la lista de espera al árbol principal.

(Puede leer más en este artículo ) .
Tales bloqueos deberían entrar en conflicto incluso entre procesos del mismo grupo paralelo, que implementa este parche. Pero estos bloqueos nunca pueden conducir a puntos muertos, por lo que se excluyen del análisis.

Para el usuario, en general, nada cambia, pero este parche es importante porque, en primer lugar, allana el camino para INSERTAR y COPIAR en paralelo, y en segundo lugar, elimina uno de los cuellos de botella de PostgreSQL en condiciones de alta carga (que se puede escuchar en el informe HL ++ ).

La seguridad


Los
primos SKH PRH reemplazaron a los primos EDH reemplazados (claves efímeras Diffie-Hellman) utilizando el protocolo SKIP ahora desaparecido.

initdb: la configuración predeterminada para la autenticación
ha cambiado La configuración de acceso predeterminada para las conexiones locales y de red ha cambiado cuando se inicia initdb. Ahoraserápg_hba.confpara conexiones locales en lugar del método de autenticación(o md5 si no es compatible con el igual), ypara conexiones de red. Inicialmente, se discutieron medidas más liberales: advertencia en la documentación. Entonces más dura:. Como resultado, decidimos limitarnos ay. Usando explicit_bzerotrustpeermd5scram-sha-256peermd5


Parche importante Las funciones del sistema operativo bzero () y explicit_bzero () escriben bytes que contienen en las áreas de memoria indicadas '\0'(ver, por ejemplo , Linux). Estos parches son solo el comienzo: hay muchas secciones de memoria en las que pueden permanecer las contraseñas y otra información confidencial. Decidimos comenzar desde lugares como libpq, en el que todo el archivo con contraseñas puede permanecer en la memoria después de leer .pgpass, y desde la limpieza después de cerrar la conexión. En be-secure-common.c ahora hay una sobrescritura de la frase secreta ingresada en SSL, que aparece en la línea (ruta) del error.

Se agregó el parámetro "password_protocol" a libpq
Este parche permite a libpq controlar qué protocolo de transferencia de contraseña se usa durante la conexión. Después de recibir este parámetro, libpq rechazará la autenticación si el protocolo es más débil que el especificado. Por defecto, este parámetro plaintext, es decir, todos los protocolos son adecuados.

Acceso obligatorio para TRUNCATE
Este parche permite que las extensiones incorporen el Control de acceso obligatorio (MAC) para una operación TRUNCATE. Los derechos sobre él ahora serán verificados por la extensión sepgsql . La política de referencia de SELinux y las distribuciones de Linux basadas en Redhat no admiten la comprobación de SELinux en db_table {truncate}. En este caso, sepgsql se usará con 'deny_unknown' igual a 1, y TRUNCATE fallará.

Disponibilidad de GUC ssl_passphrase_command
Un parche simple pero útil. Ahora el valor del parámetro ssl_passphrase_command solo lo verá el superusuario. El parámetro especifica un comando externo que se llama cuando se requiere una contraseña para descifrar un archivo SSL, por ejemplo, una clave privada.

Localización


Versiones de reglas de clasificación de libc
Para las reglas de clasificación de ICU, los números de versión se almacenan en la base de datos. Cada vez que se usa la regla (clasificación, comparación de caracteres), el número de versión guardado se verifica con la versión actual en la biblioteca de la UCI en el sistema operativo, y en caso de discrepancias, se emite una advertencia. Esto le permite descubrir que ciertos índices creados de acuerdo con las reglas de clasificación modificadas pueden ser incorrectos y deberían reconstruirse. Al reconstruir los índices con el comandoALTER COLLATION ... REFRESH VERSION, se actualiza la versión de la regla de clasificación en la base de datos y ya no se emiten advertencias.

Pero eso fue solo para la UCI. Ahora el número de versión también se almacena para las reglas de clasificación de libc:

SELECT collname, collversion FROM pg_collation WHERE collname = 'ru_RU';

 collname | collversion
----------+-------------
 ru_RU    | 2.27

Lo que hace posible emitir advertencias cuando una biblioteca cambia en el sistema operativo. Muy relevante a la luz de la transición a glibc 2.28, donde muchas reglas de clasificación han cambiado, y los índices correspondientes deberían reconstruirse.

Pero hasta que cambiaron a 2.28, todo está tranquilo:
ALTER COLLATION "ru_RU" REFRESH VERSION;

NOTICE:  version has not changed
ALTER COLLATION

Búsqueda de texto completo


Búsqueda de texto completo para el idioma griego
No hay comentarios.

dict_int aprendió a manejar valores absolutos.
El diccionario de plantillas dict_int (también conocido como extensión) agregó la capacidad de eliminar el signo de un número.


CREATE EXTENSION dict_int;
SELECT ts_lexize('intdict', '-123');

ts_lexize
-----------
 {-123}
(1 row)

ALTER TEXT SEARCH DICTIONARY intdict (ABSVAL = true);
SELECT ts_lexize('intdict', '-123');

ts_lexize
-----------
 {123}
(1 row)

Es decir, esta vez se reconoció el valor absoluto.

Fraccionamiento


ANTES de los
disparadores de filaBEFOREen una tabla particionadaEn la versión 12, no puede crear disparadores de filaen una tabla particionada. En secciones separadas, por favor, pero no en toda la tabla a la vez. Ahora, unBEFORE FOR EACH ROWactivador creado en una tabla particionada se heredará automáticamente y funcionará para todas las secciones. Pero con la condición de que si se activaUPDATE, la clave de partición solo se puede cambiar dentro de la sección actual.

Soporte para tablas particionadas en replicación lógica
Anteriormente, incluir una tabla particionada en una publicación causaba un error:

CREATE PUBLICATION pub FOR TABLE p;

ERROR:  "p" is a partitioned table
DETAIL:  Adding partitioned tables to publications is not supported.
HINT:  You can add the table partitions individually.

Ahora funciona.

Algoritmo
de unión seccional mejorado A partir de la versión 11, el planificador puede unir tablas particionadas sección por sección, pero solo si los límites de las secciones coinciden exactamente. Ahora el algoritmo se ha mejorado: funcionará si la sección de una tabla está completamente incluida en la sección de otra, incluso si sus tamaños no coinciden (por ejemplo, si una tabla se divide por día y la otra por mes). El nuevo algoritmo funciona para particionar por rangos y por listas.

UNIÓN SECUNDARIA COMPLETA SECCIONAL La unión seccionalizada
ahora funciona para combinaciones externas completas grabadas con una frase USING.

tableam


En esta área atractiva y prometedora, pero difícil, no hay avances radicales con respecto a PostgreSQL 12. No hay almacenamientos de plug-in listos como zheapotros que no sean el montón), pero el trabajo continúa en la API.

Un mayor nivel de abstracción para determinar el tamaño de una tabla
Robert Haas reescribió el código, cambiando su arquitectura a favor de las capas abstractas, de modo que no habría necesidad de duplicar el código en el futuro. Esta pieza se refiere al estimate_rel_sizetamaño de las capas (horquillas) de la mesa.

Puede usar métodos de acceso a tablas con relcache.
Este parche trae las capacidades de administración de memoria de los métodos de acceso a tablas a las capacidades de los métodos de índice.

tableam y TOAST
TOAST están diseñados en gran medida para el almacenamientoheapPor lo tanto, al crear nuevos métodos de acceso a la tabla, puede ir de dos maneras: ayudar a los desarrolladores de nuevos métodos a integrar insertar, actualizar y eliminar registros de TOAST en ellos o delegar el trabajo con TOAST para codificar utilizando el almacenamiento tradicional de PostgreSQL: almacenamiento dinámico. Una serie de 5 parches utiliza ranuras de tupla para implementar operaciones de inserción / actualización / eliminación y puede ayudar a los que van en ambos sentidos.

fsync


Manejo de errores de fsync en pg_receivewal y pg_recvlogical
La lucha contra fsync () continúa. PostgreSQL cree que una llamada fsync () exitosa significa que todos los datos del archivo se han vaciado al disco, pero esto no siempre ocurre (depende del sistema operativo) y puede provocar la pérdida de datos. PG13 decidió que era necesario tratar con los servicios públicospg_receivewalypg_recvlogical. Actualmente, el comportamiento predeterminado es el siguiente: estas utilidades escribirán errores fsync en los registros, restaurarán la conexión y continuarán como si nada hubiera pasado. Como resultado, el WAL contiene información sobre los archivos que se copiaron correctamente y que, de hecho, no se volcaron correctamente en el disco. Por lo tanto, es mejor interrumpir la utilidad. También se discutió el destino de pg_dump, pg_basebackup, pg_rewind y pg_checksums, pero hasta ahora se han limitado a estos dos.

Protección contra la configuración de indicadores incorrectos para fsync ()
Este parche verifica si los indicadores están configurados correctamente al recibir el descriptor de archivo para fsync (): los directorios están abiertos solo para lectura y los archivos para escritura o ambos.

Copia de seguridad y replicación


Pausa durante la recuperación antes de llegar al punto de recuperación
Si durante la recuperación los WAL han finalizado, perorecovery_target_timeno han alcanzado elespecificado, el servidor completa la recuperación y cambia al modo de funcionamiento normal. Ahora ya no será así. El proceso de recuperación se pausará, como se informa en el registro, y el administrador tendrá la oportunidad de insertar los segmentos WAL que faltan y continuar la recuperación.

El parámetro ignore_invalid_pages
Cuando el proceso de recuperación en una réplica encuentra un enlace a una página no válida en el registro WAL,panic-asucede. La inclusión del parámetro ayudará a superarlo.ignore_invalid_pages. La recuperación continuará con la posible pérdida de integridad, datos y otras consecuencias más graves. El parámetro está destinado a los desarrolladores de servidores y debe usarse en aquellos casos en los que aún deba intentar completar la recuperación e iniciar la réplica.

Cambiando primary_conninfo sin necesidad de reiniciar
el parche de Sergey Kornilov, que le permite cambiar la configuración primary_conninfo, primary_slot_namey wal_receiver_create_temp_slotsin necesidad de reiniciar el servidor. En realidad, por el bien de esto, abandonaron el archivo recovery.confen la versión 12. Los manifiestos de

copia de seguridad
Pg_basebackup ahora crean un "manifiesto": un archivo JSON que contiene información sobre la copia de seguridad realizada (nombres y tamaños de archivo, archivos WAL necesarios, así como sumas de comprobación para todo y todo).
La nueva utilidad pg_validatebackup verifica que las copias de seguridad cumplan con el manifiesto, y también verifica la disponibilidad y corrección de los archivos WAL necesarios para la recuperación utilizando la utilidad pg_waldump (esto se aplica solo a los archivos WAL dentro de la copia de seguridad en sí, y no en el archivo).
Esto le permitirá detectar situaciones en las que los archivos de copia de seguridad se dañaron o desaparecieron, o cuando la recuperación se hizo imposible debido a la falta de los archivos de registro necesarios.

Limitación de datos no leídos por la ranura de replicación La ranura de replicación
es un mecanismo conveniente pero peligroso: si el cliente no lee los datos de la ranura a tiempo, los registros WAL no leídos pueden ocupar todo el espacio en el servidor. Ahora usando el parámetromax_slot_wal_keep_sizePuede establecer un límite en la cantidad máxima de espacio en disco que pueden ocupar los datos no leídos. Si en el siguiente punto de control resulta que se excede el tamaño, se deshabilita la ranura y se libera el lugar.

Ventanas


Compatibilidad con sockets Unix en Windows Los
sockets de dominio Unix son compatibles con Windows 10, aunque están deshabilitados de forma predeterminada.

Documentación


Hay dos nuevas aplicaciones en la documentación.
Después de una larga discusión , apareció el Apéndice M. Glosario . Actualmente hay 101 términos en el glosario.

La capacidad de resaltar el color de los mensajes de diagnóstico de las utilidades de la consola utilizando una variable PG_COLORera anterior. Esto ahora está documentado en el Apéndice N. Soporte de color . La intención original de Peter Eisentrout en este parche era activar la salida coloreada de forma predeterminada. Y para aquellos que no querían esto, se propuso establecer explícitamente la variableNO_COLOR. Pero hubo más opositores a la diferenciación de color de los mensajes entre los que discutieron el parche. Por lo tanto, decidieron solo documentar las oportunidades disponibles. Y tenemos una nueva sección del primer nivel en la documentación.



PG13, , PG14 . , . .

All Articles