psql查询CASE vs多个选择大数据集 - 性能

时间:2018-05-14 08:53:43

标签: sql postgresql knex.js

对于大型数据集,哪个选项更好,选择vs case

案例:

SELECT SUM(CASE WHEN(created_at > (CURRENT_DATE - INTERVAL '1 days')) THEN 1 ELSE 0 END) as day_count,
SUM(CASE WHEN(created_at > (CURRENT_DATE - INTERVAL '1 months')) THEN 1 ELSE 0 END) as month_count,
SUM(CASE WHEN(created_at > (CURRENT_DATE - INTERVAL '3 months')) THEN 1 ELSE 0 END) as quater_count,
SUM(CASE WHEN(created_at > (CURRENT_DATE - INTERVAL '6 months')) THEN 1 ELSE 0 END) as half_year_count,
SUM(CASE WHEN(created_at > (CURRENT_DATE - INTERVAL '1 years')) THEN 1 ELSE 0 END) as year_count,
count(*) as total_count from wallets;

多项选择查询:

SELECT count(*) from wallets where created_at > CURRENT_DATE - INTERVAL '1 days';
SELECT count(*) from wallets where created_at > CURRENT_DATE - INTERVAL '1 months';
SELECT count(*) from wallets where created_at > CURRENT_DATE - INTERVAL '3 months';
SELECT count(*) from wallets where created_at > CURRENT_DATE - INTERVAL '6 months';
SELECT count(*) from wallets where created_at > CURRENT_DATE - INTERVAL '1 years';
SELECT count(*) from wallets;

要求是按日,月,3个月,6个月和每年查找钱包数。 如果我选择多个选择,那么将需要6个查询来获取数据。

使用switch case我们可以在一个查询中获取数据,但我不确定最佳做法是将switch case用于大型数据集。

请查看下面的查询分析,我的数据库中只有10条记录:

案例查询分析:

enter image description here

多个查询分析:

enter image description here

3 个答案:

答案 0 :(得分:2)

单个查询会更好。使用filter

可以提高性能
SELECT COUNT(*) FILTER (WHERE created_at > (CURRENT_DATE - INTERVAL '1 days')) as day_count,
       COUNT(*) FILTER (WHERE created_at > (CURRENT_DATE - INTERVAL '1 months'))  as month_count,
       COUNT(*) FILTER (WHERE created_at > (CURRENT_DATE - INTERVAL '3 months')) as quater_count,
       COUNT(*) FILTER (WHERE created_at > (CURRENT_DATE - INTERVAL '6 months')) as half_year_count,
       COUNT(*) FILTER (WHERE created_at > (CURRENT_DATE - INTERVAL '1 years')) as year_count,
       COUNT(*) as total_count 
FROM wallets;

如果你有created_at的索引,那么这也应该有助于Postgres优化只使用该索引。

答案 1 :(得分:0)

从knex的角度来看,区别在于可以通过单独的连接向DB发送多个查询并并行执行。执行单个查询可能会在整体上提高性能,从而减少数据库服务器上的压力/数据传输开销。

执行查询的第一种方法的最大缺点是你无法使用knex很好地构建它,并且对于读取代码的人来说它看起来很糟糕。

实现这种将多个查询打包为单一的更好方法是使用postgres with语句(公用表表达式)https://www.postgresql.org/docs/9.6/static/queries-with.html,其中knexalso支持http://knexjs.org/#Builder-with

编辑:或者只是在单一选择中进行多次查询,有点像Gordon Linoff建议:

knex
  .select( 
    knex('wallets')
      .where('createad_at', '>', knex.raw("CURRENT_DATE - INTERVAL '1 days'"))
      .count()
      .as('lastDay'),
    knex('wallets')
      .where('createad_at', '>', knex.raw("CURRENT_DATE - INTERVAL '1 months'"))
      .count()
      .as('lastMonth'),
      ... rest of the queries ...
  );

https://runkit.com/embed/wsy01ar1hb73

postgresql应该能够使用Gordon的回答促进的类似计划来优化多个子查询。

答案 2 :(得分:0)

我可以做一个有根据的猜测。没有实际的数据测试几乎没用。

多选查询更容易通过数据库平面进行优化。 PostgreSQL 9.6+可以使用index only scans。它可能会以一些非常快速的查询结束。

案例非常难以阅读。我担心没有人可以为此编写索引,查询将被强制扫描整个表。这可能是一个非常缓慢的操作。