当前位置: 首页 > 知识库问答 >
问题:

如何使用DISTINCT ON和JOIN MULTY values优化SQL查询?

司寇光华
2023-03-14

我有一个这样的查询,其中join~6000个值

SELECT DISTINCT ON(user_id)
                user_id,
                finished_at as last_deposit_date,
                CASE When currency = 'RUB' Then amount_cents  END as last_deposit_amount_cents
            FROM    payments
            JOIN (VALUES (5),(22),(26)) --~6000 values
            AS v(user_id) USING (user_id)
            WHERE action = 'deposit' 
                AND success = 't'
                AND currency IN ('RUB')
            ORDER BY user_id, finished_at DESC

多值查询的查询计划:

Unique  (cost=444606.97..449760.44 rows=19276 width=24) (actual time=6129.403..6418.317 rows=5991 loops=1)
  Buffers: shared hit=2386527, temp read=7807 written=7808
  ->  Sort  (cost=444606.97..447183.71 rows=1030695 width=24) (actual time=6129.401..6295.457 rows=1877039 loops=1)
        Sort Key: payments.user_id, payments.finished_at DESC
        Sort Method: external merge  Disk: 62456kB
        Buffers: shared hit=2386527, temp read=7807 written=7808
        ->  Nested Loop  (cost=0.43..341665.35 rows=1030695 width=24) (actual time=0.612..5085.376 rows=1877039 loops=1)
              Buffers: shared hit=2386521
              ->  Values Scan on "*VALUES*"  (cost=0.00..75.00 rows=6000 width=4) (actual time=0.002..4.507 rows=6000 loops=1)
              ->  Index Scan using index_payments_on_user_id on payments  (cost=0.43..54.78 rows=172 width=28) (actual time=0.010..0.793 rows=313 loops=6000)
                    Index Cond: (user_id = "*VALUES*".column1)
                    Filter: (success AND ((action)::text = 'deposit'::text) AND ((currency)::text = 'RUB'::text))
                    Rows Removed by Filter: 85
                    Buffers: shared hit=2386521
Planning time: 5.886 ms
Execution time: 6429.685 ms

我使用PosgreSQL 10.8.0。有没有可能加快这个查询的速度?

我尝试用递归替换DISTINCT:

WITH RECURSIVE t AS (
 (SELECT min(user_id) AS user_id FROM payments)
 UNION ALL
 SELECT (SELECT min(user_id) FROM payments  
 WHERE user_id > t.user_id      
 ) AS user_id FROM
t   
  WHERE t.user_id IS NOT NULL
 )
SELECT payments.* FROM t
JOIN (VALUES (5),(22),(26)) --~6000 VALUES
AS v(user_id) USING (user_id)
, LATERAL (
 SELECT user_id,
        finished_at as last_deposit_date,
        CASE When currency = 'RUB' Then amount_cents  END as last_deposit_amount_cents FROM payments            
        WHERE payments.user_id=t.user_id
            AND action = 'deposit' 
        AND success = 't'
        AND currency IN ('RUB')     
        ORDER BY finished_at DESC LIMIT 1
) AS payments

WHERE t.user_id IS NOT NULL;

但结果更慢。

哈希连接(成本=418.67..21807.22行=3000宽度=24)(实际时间=16.804..10843.174行=5991循环=1)哈希Cond:(t.user_id="VALUES"。专栏1)缓冲区:共享命中=6396763 CTE t-

共有1个答案

督坚白
2023-03-14

对于此查询:

SELECT DISTINCT ON (user_id)
       p.user_id,
       p.finished_at as last_deposit_date,
       (CASE WHEN p.currency = 'RUB' THEN p.amount_cents  END) as last_deposit_amount_cents
FROM payments p JOIN
     (VALUES (5),( 22), (26) --~6000 values
     ) v(user_id)
     USING (user_id)
WHERE p.action = 'deposit' AND
      p.success = 't' ND
      p.currency = 'RUB'
ORDER BY p.user_id, p.finished_at DESC;

我不完全理解CASE表达式,因为WHERE正在过滤掉所有其他值。

这就是说,我希望(操作、成功、货币、用户id、在desc完成)的索引会有所帮助。

 类似资料:
  • 问题内容: 我有一个查询,使用带通配符的“ like”来搜索客户端。例如: 它还可以在“ where”子句中使用较少的参数,例如: 谁能说出优化这种查询性能的最佳方法是什么?也许我需要创建一个索引?该表在生产中最多可以有1000K条记录。 问题答案: 要在模式具有表单的位置上做很多事情,您需要查找SQL Server的全文本索引功能,并使用代替。照原样,您正在执行全表扫描,因为普通索引对搜索以通配

  • 问题内容: 在这里很难说出要问什么。这个问题是模棱两可,含糊不清,不完整,过于宽泛或夸张的,不能以目前的形式合理地回答。如需帮助澄清此问题以便可以重新打开, 请访问帮助中心。 8年前关闭。 有一个查询运行得比我想要的慢,但是我无法共享详细信息。该查询已经返回了正确的结果,并且已经对其进行了重构,但是我无法使其足够快地运行。谓词在可能的情况下已经是可Sarg- able 的。它已经正确地使用了联接,

  • 我一直在使用Jooq生成的代码模式进行如下查询: 它与RecordMapperProvider一起根据表和模型类确定使用哪个RecordMapper: 这是我试图实现的一个例子: 新的查询包含了该组件,并且它正在改变传递给RecordMapperProvider的RecordType。这个新的RecordType不再与生成的代码匹配。 我的问题是:是否有一种解决方案,可以在查询中使用distinc

  • 1. 前言 在前面的小节和实战中,我们一直在学习和讨论如何写 SQL,如何用 SQL 完成一个业务功能点。本小节,我们将以优化的角度来探讨一下如何优化 SQL,让 SQL 更加高效的运行。 SQL 优化是一个很大的专题,本节会介绍几种常见的 SQL 优化手段和一些好用的优化工具。 2. 工具 SQL 优化并不简单,因此我们可以利用一些工具来帮助我们。 2.1 soar soar是小米开源的一款 S

  • 问题内容: 我不太擅长SQL,因此我要求你们提供有关编写查询的帮助。 [SQL查询-表连接问题]https://codingdict.com/questions/208252) 我得到了答案,并且可以正常工作!它只是明显的缓慢。我讨厌这样做,但是我真的希望有人在那里推荐一些优化查询的方法。我什至没有自己尝试过,因为我对SQL不够了解,甚至无法开始使用谷歌搜索。 问题答案: 可能有帮助的是在要加入的

  • 本文向大家介绍如何进行SQL优化?相关面试题,主要包含被问及如何进行SQL优化?时的应答技巧和注意事项,需要的朋友参考一下 (1)选择正确的存储引擎 MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算