[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-deep-evm-25-particionamiento-tablas-postgresql":3},{"article":4,"author":42},{"id":5,"category_id":6,"title":7,"slug":8,"excerpt":9,"content_md":10,"content_html":11,"locale":12,"author_id":13,"published":14,"published_at":15,"meta_title":16,"meta_description":17,"focus_keyword":18,"og_image":19,"canonical_url":19,"robots_meta":20,"created_at":15,"updated_at":15,"tags":21,"category_name":22,"related_articles":23},"d8000000-0000-0000-0000-000000000125","a0000000-0000-0000-0000-000000000085","Deep EVM #25: Particionamiento de Tablas en PostgreSQL — Cuando Tu Tabla Supera 10M+ Filas","deep-evm-25-particionamiento-tablas-postgresql","Guía práctica de particionamiento en PostgreSQL para tablas grandes. Cubre particionamiento por rango, lista y hash con ejemplos reales, estrategias de migración y planificación de consultas.","## Cuándo particionar\n\nPostgreSQL maneja millones de filas sin problemas, pero cuando una tabla crece más allá de ciertos umbrales, el rendimiento se degrada:\n\n- Escaneos secuenciales se vuelven prohibitivamente lentos\n- Los índices crecen y ya no caben en memoria\n- VACUUM tarda horas y bloquea operaciones\n- Backups se vuelven inmanejables\n\nEl particionamiento divide una tabla lógica en múltiples tablas físicas, permitiendo al planificador de consultas escanear solo las particiones relevantes.\n\n## Tipos de particionamiento\n\n### Por rango (RANGE)\nIdeal para datos temporales:\n\n```sql\nCREATE TABLE transactions (\n    id BIGSERIAL,\n    block_number BIGINT NOT NULL,\n    tx_hash BYTEA NOT NULL,\n    from_addr BYTEA,\n    to_addr BYTEA,\n    value NUMERIC,\n    created_at TIMESTAMPTZ DEFAULT NOW()\n) PARTITION BY RANGE (block_number);\n\nCREATE TABLE transactions_0_1m\n    PARTITION OF transactions\n    FOR VALUES FROM (0) TO (1000000);\n\nCREATE TABLE transactions_1m_2m\n    PARTITION OF transactions\n    FOR VALUES FROM (1000000) TO (2000000);\n```\n\n### Por lista (LIST)\nIdeal para categorías discretas:\n\n```sql\nCREATE TABLE pool_events (\n    id BIGSERIAL,\n    chain TEXT NOT NULL,\n    pool_address BYTEA,\n    event_type TEXT,\n    data JSONB\n) PARTITION BY LIST (chain);\n\nCREATE TABLE pool_events_ethereum\n    PARTITION OF pool_events FOR VALUES IN ('ethereum');\nCREATE TABLE pool_events_arbitrum\n    PARTITION OF pool_events FOR VALUES IN ('arbitrum');\nCREATE TABLE pool_events_optimism\n    PARTITION OF pool_events FOR VALUES IN ('optimism');\n```\n\n### Por hash (HASH)\nDistribuye datos uniformemente:\n\n```sql\nCREATE TABLE address_balances (\n    address BYTEA NOT NULL,\n    token BYTEA NOT NULL,\n    balance NUMERIC\n) PARTITION BY HASH (address);\n\nCREATE TABLE address_balances_0\n    PARTITION OF address_balances FOR VALUES WITH (MODULUS 4, REMAINDER 0);\nCREATE TABLE address_balances_1\n    PARTITION OF address_balances FOR VALUES WITH (MODULUS 4, REMAINDER 1);\n```\n\n## Partition pruning\n\nEl planificador de PostgreSQL elimina automáticamente particiones no relevantes:\n\n```sql\nEXPLAIN SELECT * FROM transactions WHERE block_number = 1500000;\n-- Solo escanea transactions_1m_2m\n```\n\nPara que funcione, la clave de partición debe estar en la cláusula WHERE.\n\n## Migración de tabla existente\n\n```sql\n-- 1. Crear tabla particionada nueva\nCREATE TABLE transactions_new (...) PARTITION BY RANGE (block_number);\n\n-- 2. Crear particiones\nCREATE TABLE transactions_new_0_1m ...;\n\n-- 3. Copiar datos (en ventana de mantenimiento)\nINSERT INTO transactions_new SELECT * FROM transactions;\n\n-- 4. Renombrar\nALTER TABLE transactions RENAME TO transactions_old;\nALTER TABLE transactions_new RENAME TO transactions;\n\n-- 5. Verificar y eliminar antigua\nDROP TABLE transactions_old;\n```\n\n## Conclusión\n\nEl particionamiento de tablas en PostgreSQL es esencial para mantener el rendimiento cuando las tablas crecen más allá de millones de filas. Elegir la estrategia correcta (rango, lista o hash) depende del patrón de acceso a los datos.","\u003Ch2 id=\"cu-ndo-particionar\">Cuándo particionar\u003C\u002Fh2>\n\u003Cp>PostgreSQL maneja millones de filas sin problemas, pero cuando una tabla crece más allá de ciertos umbrales, el rendimiento se degrada:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Escaneos secuenciales se vuelven prohibitivamente lentos\u003C\u002Fli>\n\u003Cli>Los índices crecen y ya no caben en memoria\u003C\u002Fli>\n\u003Cli>VACUUM tarda horas y bloquea operaciones\u003C\u002Fli>\n\u003Cli>Backups se vuelven inmanejables\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>El particionamiento divide una tabla lógica en múltiples tablas físicas, permitiendo al planificador de consultas escanear solo las particiones relevantes.\u003C\u002Fp>\n\u003Ch2 id=\"tipos-de-particionamiento\">Tipos de particionamiento\u003C\u002Fh2>\n\u003Ch3>Por rango (RANGE)\u003C\u002Fh3>\n\u003Cp>Ideal para datos temporales:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-sql\">CREATE TABLE transactions (\n    id BIGSERIAL,\n    block_number BIGINT NOT NULL,\n    tx_hash BYTEA NOT NULL,\n    from_addr BYTEA,\n    to_addr BYTEA,\n    value NUMERIC,\n    created_at TIMESTAMPTZ DEFAULT NOW()\n) PARTITION BY RANGE (block_number);\n\nCREATE TABLE transactions_0_1m\n    PARTITION OF transactions\n    FOR VALUES FROM (0) TO (1000000);\n\nCREATE TABLE transactions_1m_2m\n    PARTITION OF transactions\n    FOR VALUES FROM (1000000) TO (2000000);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Por lista (LIST)\u003C\u002Fh3>\n\u003Cp>Ideal para categorías discretas:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-sql\">CREATE TABLE pool_events (\n    id BIGSERIAL,\n    chain TEXT NOT NULL,\n    pool_address BYTEA,\n    event_type TEXT,\n    data JSONB\n) PARTITION BY LIST (chain);\n\nCREATE TABLE pool_events_ethereum\n    PARTITION OF pool_events FOR VALUES IN ('ethereum');\nCREATE TABLE pool_events_arbitrum\n    PARTITION OF pool_events FOR VALUES IN ('arbitrum');\nCREATE TABLE pool_events_optimism\n    PARTITION OF pool_events FOR VALUES IN ('optimism');\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Por hash (HASH)\u003C\u002Fh3>\n\u003Cp>Distribuye datos uniformemente:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-sql\">CREATE TABLE address_balances (\n    address BYTEA NOT NULL,\n    token BYTEA NOT NULL,\n    balance NUMERIC\n) PARTITION BY HASH (address);\n\nCREATE TABLE address_balances_0\n    PARTITION OF address_balances FOR VALUES WITH (MODULUS 4, REMAINDER 0);\nCREATE TABLE address_balances_1\n    PARTITION OF address_balances FOR VALUES WITH (MODULUS 4, REMAINDER 1);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"partition-pruning\">Partition pruning\u003C\u002Fh2>\n\u003Cp>El planificador de PostgreSQL elimina automáticamente particiones no relevantes:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-sql\">EXPLAIN SELECT * FROM transactions WHERE block_number = 1500000;\n-- Solo escanea transactions_1m_2m\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Para que funcione, la clave de partición debe estar en la cláusula WHERE.\u003C\u002Fp>\n\u003Ch2 id=\"migraci-n-de-tabla-existente\">Migración de tabla existente\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-sql\">-- 1. Crear tabla particionada nueva\nCREATE TABLE transactions_new (...) PARTITION BY RANGE (block_number);\n\n-- 2. Crear particiones\nCREATE TABLE transactions_new_0_1m ...;\n\n-- 3. Copiar datos (en ventana de mantenimiento)\nINSERT INTO transactions_new SELECT * FROM transactions;\n\n-- 4. Renombrar\nALTER TABLE transactions RENAME TO transactions_old;\nALTER TABLE transactions_new RENAME TO transactions;\n\n-- 5. Verificar y eliminar antigua\nDROP TABLE transactions_old;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"conclusi-n\">Conclusión\u003C\u002Fh2>\n\u003Cp>El particionamiento de tablas en PostgreSQL es esencial para mantener el rendimiento cuando las tablas crecen más allá de millones de filas. Elegir la estrategia correcta (rango, lista o hash) depende del patrón de acceso a los datos.\u003C\u002Fp>\n","es","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:31.648416Z","Particionamiento de Tablas en PostgreSQL — Cuando Tu Tabla Supera 10M+ Filas","Guía práctica de particionamiento PostgreSQL: rango, lista, hash, partition pruning y estrategias de migración.","PostgreSQL particionamiento tablas",null,"index, follow",[],"DevOps",[24,30,36],{"id":25,"title":26,"slug":27,"excerpt":28,"locale":12,"category_name":22,"published_at":29},"d8000000-0000-0000-0000-000000000128","Deep EVM #28: Pipeline de Datos de Alto Rendimiento — Inserciones Batch, COPY y Resolución de Conflictos","deep-evm-28-pipeline-datos-alto-rendimiento-batch","Construye pipelines de datos de alto rendimiento con PostgreSQL usando protocolo COPY, patrones de upsert masivo, ajuste de WAL, connection pooling con PgBouncer y monitoreo.","2026-03-28T10:44:31.664358Z",{"id":31,"title":32,"slug":33,"excerpt":34,"locale":12,"category_name":22,"published_at":35},"d8000000-0000-0000-0000-000000000127","Deep EVM #27: Rendimiento de PostgreSQL a Escala — Índices, VACUUM y Optimización de Consultas","deep-evm-27-rendimiento-postgresql-indices-vacuum","Optimiza PostgreSQL para alto rendimiento: tipos de índices y cuándo usarlos, VACUUM y autovacuum, EXPLAIN ANALYZE, y técnicas de optimización de consultas para tablas de millones de filas.","2026-03-28T10:44:31.659082Z",{"id":37,"title":38,"slug":39,"excerpt":40,"locale":12,"category_name":22,"published_at":41},"d8000000-0000-0000-0000-000000000126","Deep EVM #26: Sharding vs Particionamiento — Arquitectura para Tablas Masivas","deep-evm-26-sharding-vs-particionamiento-tablas-masivas","Comprende las diferencias entre sharding y particionamiento: cuándo usar cada uno, estrategias de clave de distribución, consistencia entre shards, y patrones para escalar PostgreSQL horizontalmente.","2026-03-28T10:44:31.653366Z",{"id":13,"name":43,"slug":44,"bio":45,"photo_url":19,"linkedin":19,"role":46,"created_at":47,"updated_at":47},"Open Soft Team","open-soft-team","The engineering team at Open Soft, building premium software solutions from Bali, Indonesia.","Engineering Team","2026-03-28T08:31:22.226811Z"]