¿Particionar o no particionar?

8

Después de haber leído varias preguntas sobre SO, publicaciones de blog externas y manual

Todavía me pregunto si debería seguir con la partición considerando mi caso o no.

El caso - simplificado

Almacenar datos del cliente. Todos los nombres de las tablas mencionadas a continuación están compuestos por claridad.

  1. Tener objetos que son identificables por el cliente y que son seres no físicos, también sus objetos físicos en los que realmente se almacenan en caso de que necesiten enviar algunos objetos al cliente a pedido, o procesarlos de alguna otra manera. Están mapeados en una relación de muchos a muchos. objects_nonphysical, objects_physical, objects_mapping_table.

  2. La segunda relación de muchos a muchos es entre esos objetos no físicos y sus métricas. Hay objetos que están vinculados con algunas métricas. metrics,metrics_objects_nonphysical

  3. Tanto los objetos no físicos como los físicos tienen sus tablas de jerarquía que son relaciones padre-hijo. objects_nonphysical_hierarchy,objects_physical_hierarchy

Dependiendo de las necesidades y requisitos de cada cliente, los datos sobre objetos físicos pueden suministrarse o pueden necesitarse desde cero. Básicamente, lo que necesito hacer es:

  • Mantenga un sistema interno rápido INSERTy SELECTenunciado, porque aquí es donde se realizará el mapeo.

  • Mantenga el sistema para que el cliente externo pueda ver y operar en sus objetos no físicos : recuperación rápida de datos. Gran necesidad de eficiencia para las SELECTdeclaraciones: esta información está disponible para que muchos clientes la busquen cuando lo deseen.

Mi consideracion

Puede haber un cliente, que puede acceder a los datos, verlos y operar con ellos, pero no es necesario que sea un contratista del que obtuvimos los datos / para los que los procesamos.

Esto me ha llevado a introducir la partición de tablas en mi sistema, teniendo en cuenta que siempre sé en qué datos de partición deben caer ( particionamiento para contratistas ), y luego a un sistema principal para clientes externos donde necesito particiones para clientes (esto se haría con algunos Retrasar el uso de herramientas de automatización y un conjunto de reglas para reescribir los datos de manera de los clientes, de modo que para cada cliente solo escaneemos una partición para cada tabla.

Volumen de datos

Mis datos crecerán constantemente, especialmente al importar objetos y métricas de nuevos clientes. El ritmo de los nuevos datos que llegan al sistema es impredecible en este momento a largo plazo. Realmente no hay forma de medirlo sin saber quién será el próximo cliente. En este momento hay solo 2 clientes con más o menos filas de 1 millón para cada cliente en cada tabla. Pero en el futuro, predigo que nuevos clientes vendrán con un volumen de 10 millones de filas más o menos.

Preguntas

Estas preguntas están todas relacionadas entre sí.

  1. ¿Debería considerarse realmente la partición aquí, o es una exageración? Considero que es útil ya que siempre estoy escaneando exactamente una partición.
  2. Si la partición es el camino a seguir, ¿cómo hago cumplir la FKrestricción de la manera más efectiva teniendo en cuenta mis necesidades? ¿Debo ir constraint triggers, o simplemente mantenerlo en la capa de aplicación para el sistema interno, o tal vez algún otro método?
  3. Si la partición no es el camino a seguir, ¿en qué debería sumergirme?

Si no se proporcionan suficientes datos, hágamelo saber en los comentarios a continuación.

Kamil Gosciminski
fuente
3
En general, se recomienda comenzar la producción sin sobrecarga de índices, particiones, etc., si es necesario, agregue índices y particiones, etc.
alonk
1
Con la partición, solo obtendrá aceleraciones en ciertos tipos de consultas mientras recibe un golpe en otros tipos de consultas. También recibirá un golpe en las escrituras. Particionar no debería ser lo primero que buscas, y creo que estarás bien usando índices simples en el futuro previsible, y cruzarás esos puentes cuando llegues a ellos. Las filas de 5 millones no son tan grandes. Este podría ser un blog útil con comparaciones de velocidad: if-not-true-then-false.com/2009/…
dizzystar
2
Estoy de acuerdo con dizzystar, no me molestaría en este momento. Cruza ese puente si lo alcanzas. Actualmente, la partición en Postgres también hace que sea difícil (si no imposible) usar claves foráneas adecuadas (esto puede cambiar con 9.7 pero aún no se ha resuelto nada). Incluso una tabla con 50 millones de filas no es necesariamente un candidato para la partición. Si principalmente tiene condiciones de igualdad en sus consultas que reducen sustancialmente el número de filas, una buena indexación puede ayudarlo mucho .
a_horse_with_no_name
1
Para mí, no está realmente claro qué quiere decir con "particionamiento para contratistas". ¿Las tablas que usan los contratistas son diferentes de las que pertenecen a un cliente? ¿Alguna vez sucede que el cliente A tiene que acceder a los datos del cliente B? De lo contrario, separar los datos específicos del cliente en un esquema por cliente podría ser un camino a seguir, pero no necesariamente para el rendimiento, sino para la separación de preocupaciones (mayor seguridad / privacidad, etc.).
dezso

Respuestas:

1

Hay muchos extremos abiertos en su pregunta, pero la partición por cliente podría ser el camino a seguir, especialmente si:

  • esperas muchos clientes,
  • cada uno de ellos podría tener toneladas de datos ("toneladas" significa mucho más que el tamaño de caché de RAM),
  • La mayoría de sus conjuntos de datos serán mutuamente excluyentes (cada cliente ve un subconjunto de datos diferente).

Las REGLAS o los desencadenantes son una sobrecarga de rendimiento y se pueden evitar.

Considere algo en este sentido:

BEGIN;

CREATE USER tenant1;
CREATE USER tenant2;

CREATE SCHEMA app;
CREATE SCHEMA tenant1;
CREATE SCHEMA tenant2;

CREATE TABLE app.objects_nonphysical(id int);
CREATE TABLE app.objects_physical(id int);
CREATE TABLE app.objects_mapping(id int);    
CREATE TABLE tenant1.objects_nonphysical() INHERITS(app.objects_nonphysical);
CREATE TABLE tenant1.objects_physical() INHERITS(app.objects_physical);
CREATE TABLE tenant1.objects_mapping() INHERITS(app.objects_mapping);
CREATE TABLE tenant2.objects_nonphysical() INHERITS(app.objects_nonphysical);
CREATE TABLE tenant2.objects_physical() INHERITS(app.objects_physical);
CREATE TABLE tenant2.objects_mapping() INHERITS(app.objects_mapping);

GRANT USAGE ON SCHEMA tenant1 TO tenant1;
GRANT USAGE ON SCHEMA tenant2 TO tenant2;
GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA tenant1 TO tenant1;
GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA tenant2 TO tenant2;

/* TEST: simulate login as customer */
SET SESSION AUTHORIZATION tenant2;
/* No schema needed - default search_path works */
SELECT count(*) FROM objects_nonphysical; 

ROLLBACK;

No necesita ningún activador / regla para mantenerlo.

Aquí hay extremos abiertos, eso es solo un borrador ... Algunos problemas:

  • PK, FK e índices no son "heredados".
  • incluso si los crea, la PK no se aplica en la tabla maestra
  • puede superar esto utilizando la misma secuencia para todos los inquilinos
  • obviamente, la aplicación debe ajustarse para este modelo
filiprem
fuente
0

No afectará si implementa la partición ahora, pero use una sola partición hasta que su sistema realmente requiera una nueva. En cuanto al rendimiento, solo habrá una pequeña sobrecarga, para lidiar con las claves principales y demás.

Recomiendo el uso de reglas para redireccionar inserciones y una tabla externa para las claves principales (por ejemplo CREATE TABLE objects_physical_ids (id bigserial NOT NULL PRIMARY KEY), junto con un activador de función que inserta una fila en la tabla de identificadores y la copia a NEW.id (por ejemplo INSERT INTO objects_physical_ids DEFAULT VALUES RETURNING id INTO NEW.id;), y otros activadores que se ocupan de la eliminación y actualizaciones, y un activador que ejecuta esos activadores de funciones para cada tabla heredada (¡no olvide hacer esto cuando cree una nueva tabla heredada!). Luego, todas las tablas relacionadas pueden tener una FOREIGN KEYtabla de identificadores relevantes (incluidas las acciones de teclas externas como ON UPDATEo ON DELETE)

Ziggy Crueltyfree Zeitgeister
fuente
2
Las reglas y los desencadenantes definitivamente tienen gastos generales, y es fácil de medir. Además, agregan complejidad y dificultan la depuración (mucho). Además, después de pasar por este camino varias veces, sugeriría (sin reconocer todos los detalles) mantener una tabla principal vacía y una o más particiones secundarias. Al cambiar el esquema de partición, esto puede ser muy útil.
dezso