改进SQL查询(JPA?)

时间:2016-08-04 08:38:36

标签: sql performance postgresql jpa

我不太了解sql来改进数据库查询。

我有以下本机sql查询:

SELECT 
   m.id, 
   m.merchantname, 
   date_trunc('month' ,to_timestamp(t.timestamp / 1000)) as month_name,
   COUNT(*) as num_transactions, 
   cast(SUM(case when t.type IN('VEND_READER','VEND_READER_COUPON_TRANSFER') THEN t.amount ELSE 0 END) as numeric) AS sum_vend, 
   cast(SUM(case when t.type IN('REVALUE_READER','REVALUE_STARTBALANCE','REVALUE_PAYPAL','REVALUE_PROMOTION','REVALUE_CREDITCARD') THEN t.amount ELSE 0 END) AS numeric) as sum_revalue 

FROM 
   transaction t JOIN merchant m ON m.id = t.merchant_id 

WHERE 
   t.transactionstate = 'SUCCESS' 
GROUP BY 
   m.id, month_name  
ORDER BY
   m.id

我想要的只是参赛作品,包括每个商家和月份的一揽子/重估和交易次数。

如何格式化字段(可能是sql时间戳或字符串或......)

[
 {merchantID:1, merchantName:"myMerchant", vend:2030, revalue:1980, transactions:115, month:"July - 2016"},
 {merchantID:1, merchantName:"myMerchant", vend:1895, revalue:2700, transactions:100, month:"June - 2016"},
 {merchantID:1, merchantName:"myMerchant", vend:2453, revalue:1892, transactions:120, month:"May - 2016"},
 {merchantID:2, merchantName:"myMerchant2", vend:345, revalue:360, transactions:123, month:"July - 2016"},
 ...
]

如果使用JPA可以进行这样的查询,那就太棒了。但我找不到将毫秒级的纪元时间转换为一个月的方法。我们所有的时间戳(自1970年以来的毫秒数)都保存为BIGINT。

Merchant.java

@Entity
public class Merchant
{
    @Id
    @GeneratedValue
    private Long id;

    private Integer merchantGlobalID;

    private String merchantName;
}

Transaction.java

@Entity
public class Transaction
{
    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    private Merchant merchant;

    private Integer amount;

    private Long timestamp;

    @Enumerated(EnumType.STRING)
    private TransactionType type;

    @Enumerated(EnumType.STRING)
    private TransactionState transactionState;
}

我的查询有效,但性能非常糟糕。我们使用postgres数据库,当前查询使用一些特定的命令。如果有办法在JPA中获得结果,那就太好了。

修改

根据Robe Elckers的建议,我调用EXPLAIN ANALYZE查询。结果如下。我不知道我现在该做什么。

GroupAggregate  (cost=797050.04..849223.46 rows=1070224 width=559) (actual time=6913.003..7368.277 rows=16 loops=1)
  Group Key: m.id, (date_trunc('month'::text, to_timestamp(((t."timestamp" / 1000))::double precision)))
  ->  Sort  (cost=797050.04..799725.60 rows=1070224 width=559) (actual time=6792.567..7049.720 rows=1070341 loops=1)
        Sort Key: m.id, (date_trunc('month'::text, to_timestamp(((t."timestamp" / 1000))::double precision)))
        Sort Method: external merge  Disk: 57384kB
        ->  Hash Join  (cost=4.61..155797.88 rows=1070224 width=559) (actual time=0.104..6005.352 rows=1070341 loops=1)
              Hash Cond: (t.merchant_id = m.id)
              ->  Seq Scan on transaction t  (cost=0.00..130375.45 rows=1070224 width=32) (actual time=0.006..3502.850 rows=1070341 loops=1)
                    Filter: ((transactionstate)::text = 'SUCCESS'::text)
                    Rows Removed by Filter: 1598
              ->  Hash  (cost=4.27..4.27 rows=27 width=535) (actual time=0.023..0.023 rows=27 loops=1)
                    Buckets: 1024  Batches: 1  Memory Usage: 2kB
                    ->  Seq Scan on merchant m  (cost=0.00..4.27 rows=27 width=535) (actual time=0.004..0.015 rows=27 loops=1)
Planning time: 0.535 ms
Execution time: 7373.833 ms

0 个答案:

没有答案