From 7ec6edad72b6056bf3ce7a2786eb316a661371a8 Mon Sep 17 00:00:00 2001 From: Paul Copplestone Date: Thu, 30 Jul 2020 10:07:06 +0800 Subject: [PATCH 1/2] Adds materialized CTE, with performance tracking code --- src/api/tables.ts | 38 ++++++++++++++++++++++++++++++++------ src/lib/helpers.ts | 1 + 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/api/tables.ts b/src/api/tables.ts index 668ea359..2a01ec67 100644 --- a/src/api/tables.ts +++ b/src/api/tables.ts @@ -5,6 +5,21 @@ import { DEFAULT_SYSTEM_SCHEMAS } from '../lib/constants' import { Tables } from '../lib/interfaces' import sqlTemplates = require('../lib/sql') +// const { PerformanceObserver, performance } = require('perf_hooks') + +// const obs = new PerformanceObserver((items) => { +// console.log(items.getEntries()[0].duration) +// performance.clearMarks() +// }) +// obs.observe({ entryTypes: ['measure'] }) +// performance.measure('Start to Now') + +// performance.mark('A') +// performance.measure('A to Now', 'A') + +// performance.mark('B') +// performance.measure('A to B', 'A', 'B') + /** * @param {string} [include_system_schemas=false] - Return system schemas as well as user schemas */ @@ -15,17 +30,28 @@ interface QueryParams { const router = Router() router.get('/', async (req, res) => { + console.time('Total: GET tables') try { + console.time('\n\nbuild sql') const sql = getTablesSql(sqlTemplates) + console.timeEnd('\n\nbuild sql') + + console.time('GET table data') const { data } = await RunQuery(req.headers.pg, sql) + console.timeEnd('GET table data') const query: QueryParams = req.query + + console.time('remove system tables') const include_system_schemas = query?.include_system_schemas === 'true' let payload: Tables.Table[] = data if (!include_system_schemas) payload = removeSystemSchemas(data) + console.timeEnd('remove system tables') return res.status(200).json(payload) } catch (error) { console.log('throwing error', error) res.status(500).json({ error: 'Database error', status: 500 }) + } finally { + console.timeEnd('Total: GET tables') } }) @@ -122,12 +148,12 @@ router.delete('/:id', async (req, res) => { const getTablesSql = (sqlTemplates) => { const { columns, grants, policies, primary_keys, relationships, tables } = sqlTemplates return ` - WITH tables AS ( ${tables} ), - columns AS ( ${columns} ), - grants AS ( ${grants} ), - policies AS ( ${policies} ), - primary_keys AS ( ${primary_keys} ), - relationships AS ( ${relationships} ) + WITH tables AS MATERIALIZED ( ${tables} ), + columns AS MATERIALIZED ( ${columns} ), + grants AS MATERIALIZED ( ${grants} ), + policies AS MATERIALIZED ( ${policies} ), + primary_keys AS MATERIALIZED ( ${primary_keys} ), + relationships AS MATERIALIZED ( ${relationships} ) SELECT *, ${coalesceRowsToArray('columns', 'SELECT * FROM columns WHERE columns.table_id = tables.id')}, diff --git a/src/lib/helpers.ts b/src/lib/helpers.ts index e1bf75b7..69e7a96b 100644 --- a/src/lib/helpers.ts +++ b/src/lib/helpers.ts @@ -1,4 +1,5 @@ export const coalesceRowsToArray = (source: string, joinQuery: string) => { + // Note that array_to_json(array_agg(row_to_json())) seems to perform better than json_agg return ` COALESCE( ( From c715126e2b7ba70bb94006c5fdb5ce8036f02b39 Mon Sep 17 00:00:00 2001 From: Paul Copplestone Date: Thu, 30 Jul 2020 10:08:02 +0800 Subject: [PATCH 2/2] Removes perf tracking code --- src/api/tables.ts | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/api/tables.ts b/src/api/tables.ts index 2a01ec67..f2f9af51 100644 --- a/src/api/tables.ts +++ b/src/api/tables.ts @@ -5,21 +5,6 @@ import { DEFAULT_SYSTEM_SCHEMAS } from '../lib/constants' import { Tables } from '../lib/interfaces' import sqlTemplates = require('../lib/sql') -// const { PerformanceObserver, performance } = require('perf_hooks') - -// const obs = new PerformanceObserver((items) => { -// console.log(items.getEntries()[0].duration) -// performance.clearMarks() -// }) -// obs.observe({ entryTypes: ['measure'] }) -// performance.measure('Start to Now') - -// performance.mark('A') -// performance.measure('A to Now', 'A') - -// performance.mark('B') -// performance.measure('A to B', 'A', 'B') - /** * @param {string} [include_system_schemas=false] - Return system schemas as well as user schemas */ @@ -30,28 +15,17 @@ interface QueryParams { const router = Router() router.get('/', async (req, res) => { - console.time('Total: GET tables') try { - console.time('\n\nbuild sql') const sql = getTablesSql(sqlTemplates) - console.timeEnd('\n\nbuild sql') - - console.time('GET table data') const { data } = await RunQuery(req.headers.pg, sql) - console.timeEnd('GET table data') const query: QueryParams = req.query - - console.time('remove system tables') const include_system_schemas = query?.include_system_schemas === 'true' let payload: Tables.Table[] = data if (!include_system_schemas) payload = removeSystemSchemas(data) - console.timeEnd('remove system tables') return res.status(200).json(payload) } catch (error) { console.log('throwing error', error) res.status(500).json({ error: 'Database error', status: 500 }) - } finally { - console.timeEnd('Total: GET tables') } })