减少postgresql中的执行时间

问题描述 投票:1回答:3

我附上了我的查询。执行时间为60141 ms。我不知道该怎么办。但我想在短时间内执行。现在我发布了我的查询的分析和执行输出。请帮忙。

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

提前致谢。

postgresql query-performance
3个回答
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

2
投票

您应该使用IN而不是OR重写查询,如Pranesh Janarthanan的回答所示,因为OR is a performance killer

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

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

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

尝试使用这些索引和两者(这可能会给你一个“位图和”)并保持最佳效果。


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
© www.soinside.com 2019 - 2024. All rights reserved.