Node.js处理Postgres查询并返回数十万行的最佳方法

时间:2019-07-18 14:04:57

标签: node.js postgresql

我正在使用带有地图的数据仪表板。我创建了一个包含汽车位置的表,并且有一个简单的查询。

SELECT * FROM表,其中timeslice = $ {timeslice}

本来这很快,并且将必要的数据适当地发送到了前端,但是其他团队成员已经开始创建包含数百万条记录的表,现在对前端的响应时间太慢了。

在特定时间段,此查询现在返回超过60万条记录(在团队成员开始添加更多数据之前,该查询过去最多可存储1万条记录)

我在表中添加了一个索引,这将查询时间从10-15秒显着缩短到2秒。但是,前端仍然可能需要超过1分钟才能接收响应对象。我找不到任何有关提高速度的信息。

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

pg-cursor是一个可能在此有用的工具。该解决方案的官方node-postgres docs链接包括代码示例。

这将使您能够分批提取查询(确定大小)并分别对每个批处理。以前的批次将被适当地垃圾回收(除非您故意保留对那些对象的引用)。

我在下面提供了实现的简化版本:


// how many rows to retrieve at a time
const BATCH_SIZE = 100;

const cursor = client.query(new Cursor('MY QUERY'));

// wrap the whole retrieval in a promise
function processResults() {
  return new Promise((resolve, reject) => {
    (function read() {
      cursor.read(BATCH_SIZE, async (err, rows) => {
        if (err) {
          return reject(err);
        }

        // no more rows, so we're done!
        if (!rows.length) {
          return resolve();
        }

        // do something with those rows here...

        // get the next batch
        return read();
      });
    })();
  });
}

const isComplete = await processResults();

答案 1 :(得分:0)

gzip

我要尝试的第一件事是启用gzip。如果您尚未这样做,则速度可能会提高10倍,具体取决于数据的结构方式/重复次数。您可以将koa-compress用作Koa或将compression用作快递。

组/ Fitler

接下来我要尝试的是看是否有任何方法可以在将数据发送到客户端之前进行更多的处理以对数据进行分组/合并/过滤。例如您是否需要每辆汽车的位置,还是可以忽略地图上每个网格正方形中的汽车数量?然后,当用户放大时,您可以获取他们放大到的区域的更多详细数据。

缓存

如果这都不是一个选择,那么您将要研究缓存和流式传输。

如果同一用户重复访问很多次,并且数据很少更改,则可以使用localforage之类的东西在客户端存储数据,然后在向服务器发出请求时使用,您可以仅索取自给定日期以来发生更改的记录。

如果确实需要,可以将数据流传输到客户端。获取所有数据大约需要花费相同的时间,但是他们会看到一些数据随其出现。 @databases/pg有一个db.stream方法,该方法返回一个行流,您可以通过newline-json之类的管道将其序列化,然后将其序列化为响应。在客户端上,您可以在支持它们的浏览器上使用新的访存API来以流的形式检索数据,然后可以对每一行进行解析。