减少Postgresql中的执行时间

时间:2018-11-22 12:02:04

标签: postgresql query-performance

在此附上我的查询。要执行60141毫秒。我不知道该怎么办。但是我想在短时间内执行,现在我发布了我的分析并执行查询的输出。请对此提供帮助。

EXPLAIN (BUFFERS,ANALYZE) SELECT id 
FROM activitylog 
WHERE (url = '/staff/save/117' OR url = '/staff/create/117') 
AND timestamp > '1990-01-01 00:00:00' 
AND userid IN ( SELECT id 
                FROM users 
                WHERE companyid = ( SELECT companyid 
                                    FROM users 
                                    WHERE id='150' ) ) 
ORDER BY timestamp DESC

输出:

Sort  (cost=934879.83..934879.83 rows=1 width=12) (actual time=63918.947..63918.948 rows=4 loops=1)
    Sort Key: activitylog."timestamp"
    Sort Method: quicksort  Memory: 25kB
    Buffers: shared hit=168161 read=561433
    InitPlan 1 (returns $0)
    ->  Index Scan using "usersPrimary" on users users_1  (cost=0.14..8.16 rows=1 width=4) (actual time=0.005..0.005 rows=1 loops=1)
       Index Cond: (id = 150)
       Buffers: shared hit=2
    ->  Nested Loop  (cost=0.00..934871.66 rows=1 width=12) (actual time=63918.693..63918.917 rows=4 loops=1)
        Join Filter: (activitylog.userid = users.id)
        Rows Removed by Join Filter: 400
        Buffers: shared hit=168158 read=561433
    ->  Seq Scan on users  (cost=0.00..10.53 rows=25 width=4) (actual time=0.018..0.085 rows=101 loops=1)
        Filter: (companyid = $0)
        Rows Removed by Filter: 114
        Buffers: shared hit=10
    ->  Materialize  (cost=0.00..934860.39 rows=2 width=16) (actual time=120.024..632.858 rows=4 loops=101)
        Buffers: shared hit=168148 read=561433
    ->  Seq Scan on activitylog  (cost=0.00..934860.38 rows=2 width=16) (actual time=12122.376..63918.564 rows=4 loops=1)
        Filter: (("timestamp" > '2019-01-02 19:19:12.649837+00'::timestamp with time zone) AND (((url)::text = '/jobs/save/81924'::text) OR ((url)::text = '/jobs/create/81924'::text)))
        Rows Removed by Filter: 11935833
        Buffers: shared hit=168148 read=561433
    Planning time: 0.806 ms
    Execution time: 63919.748 ms

谢谢。

3 个答案:

答案 0 :(得分:4)

尝试一下,Join查询将增加索引并优化查询的执行时间

SELECT id
FROM activitylog
WHERE url in ('/staff/save/117','/staff/create/117')
  AND TIMESTAMP > '1990-01-01 00:00:00'
  AND EXISTS 
    (SELECT 1
     FROM users AS u
     JOIN users ur ON ur.CompanyID = u.CompanyID
     WHERE ur.ID = '150'
       AND u.id = activitylog.userid)
ORDER BY TIMESTAMP DESC

答案 1 :(得分:2)

您应该使用IN而不是OR来重写查询,就像Pranesh Janarthanan的答案所建议的那样,因为OR is a performance killer

此外,您需要索引来避免在activitylog上进行昂贵的顺序扫描:

CREATE INDEX ON activitylog (timestamp);
CREATE INDEX ON activitylog (url);

您需要使用哪些索引取决于各个条件的选择性。

尝试使用这些索引中的每个索引,并同时使用它们(可能会为您提供“位图和”),并保持最佳状态。

答案 2 :(得分:1)

您应该确保您具有正确的索引。另外,让我们优化查询:

SELECT id 
FROM activitylog 
WHERE url in ('/staff/save/117', '/staff/create/117') 
AND timestamp > '1990-01-01 00:00:00' 
AND 
(
(userid = 150) or
EXISTS
    (
        select 1
        from users workmate
        join users u150
        on workmate.companyid = u150.companyid and u150.id = 150
        and activitylog.userid = workmate.id
    )
)
ORDER BY timestamp DESC