psql query CASE vs Multiple select for a large data-sets - performance

psql query CASE vs Multiple select for a large data-sets - performance

对于大型数据集,哪个选项更好 multiple select 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查询:

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 个月和年查找钱包数量。 如果我使用多个 select,那么将需要 6 个查询来获取数据。

使用 switch case 我们可以在单个查询中获取数据,但我不确定对大型数据集使用 switch case 是最佳实践。

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

案例查询分析:

多查询分析:

从 knex 的角度来看,不同之处在于多个查询可以通过单独的连接发送到数据库并并行执行。仅执行单个查询可能整体性能更高,从而减少数据库服务器上的压力/数据传输开销。

第一种查询方式的最大缺点是您无法使用 knex 很好地构建它,而且对于任何阅读代码的人来说,它看起来都很糟糕。

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

编辑:或者像 Gordon Linoff 建议的那样,在单个 select 中进行多个查询:

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 的回答所提倡的类似计划来执行。

我可以做一个有根据的猜测。没有实际数据测试是没有什么用的。

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

案例很难读。恐怕没人能为此写索引,查询将被强制扫描整个table。这可能是一个非常缓慢的操作。

单一查询会更好。使用 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 优化为仅使用该索引。