Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在PostgreSQL中跨多个表索引列_Sql_Postgresql_Indexing - Fatal编程技术网

在PostgreSQL中跨多个表索引列

在PostgreSQL中跨多个表索引列,sql,postgresql,indexing,Sql,Postgresql,Indexing,我正在尝试优化以下连接查询: 通知是表示用户是否已阅读某些活动的记录。一个通知指向一个活动,但可以向许多用户通知一个活动。活动记录有一些列,例如活动所在的工作区和活动类型 此查询获取按时间顺序在特定工作区中读取的用户非注释通知 explain analyze select activity.id from activity, notification where notification.user_id = '9a51f675-e1e2-46e5-8bcd-6bc535c7e7cb' and n

我正在尝试优化以下连接查询:

通知是表示用户是否已阅读某些活动的记录。一个通知指向一个活动,但可以向许多用户通知一个活动。活动记录有一些列,例如活动所在的工作区和活动类型

此查询获取按时间顺序在特定工作区中读取的用户非注释通知

explain analyze
select activity.id from activity, notification
where notification.user_id = '9a51f675-e1e2-46e5-8bcd-6bc535c7e7cb'
and notification.read = true

and notification.activity_id = activity.id

and activity.space_id = '6d702c09-8795-4185-abb3-dc6b3e8907dc'
and activity.type != 'commented'
order by activity.end_time desc
limit 20;
问题是这个查询必须通过用户每次收到的通知来运行

Limit  (cost=4912.35..4912.36 rows=1 width=24) (actual time=138.767..138.779 rows=20 loops=1)
  ->  Sort  (cost=4912.35..4912.36 rows=1 width=24) (actual time=138.766..138.770 rows=20 loops=1)
        Sort Key: activity.end_time DESC
        Sort Method: top-N heapsort  Memory: 27kB
        ->  Nested Loop  (cost=32.57..4912.34 rows=1 width=24) (actual time=1.354..138.606 rows=447 loops=1)
              ->  Bitmap Heap Scan on notification  (cost=32.01..3847.48 rows=124 width=16) (actual time=1.341..6.639 rows=1218 loops=1)
                    Recheck Cond: (user_id = '9a51f675-e1e2-46e5-8bcd-6bc535c7e7cb'::uuid)
                    Filter: read
                    Rows Removed by Filter: 4101
                    Heap Blocks: exact=4774
                    ->  Bitmap Index Scan on notification_user_id_idx  (cost=0.00..31.98 rows=988 width=0) (actual time=0.719..0.719 rows=5355 loops=1)
                          Index Cond: (user_id = '9a51f675-e1e2-46e5-8bcd-6bc535c7e7cb'::uuid)
              ->  Index Scan using activity_pkey on activity  (cost=0.56..8.59 rows=1 width=24) (actual time=0.108..0.108 rows=0 loops=1218)
                    Index Cond: (id = notification.activity_id)
                    Filter: ((type <> 'commented'::activity_type) AND (space_id = '6d702c09-8795-4185-abb3-dc6b3e8907dc'::uuid))
                    Rows Removed by Filter: 1
Planning time: 0.428 ms
Execution time: 138.825 ms
查询性能提高了3倍

explain analyse
select activity.id from activity
INNER JOIN notification  ON  notification.user_id = '9a51f675-e1e2-46e5-8bcd-6bc535c7e7cb'
    and notification.read = true
    and notification.activity_id = activity.id
    and activity.space_id = '6d702c09-8795-4185-abb3-dc6b3e8907dc'
    and activity.type != 'commented'
order by activity.end_time desc
limit 20;

Limit  (cost=955.26..955.27 rows=1 width=24) (actual time=4.386..4.397 rows=20 loops=1)
  ->  Sort  (cost=955.26..955.27 rows=1 width=24) (actual time=4.385..4.389 rows=20 loops=1)
        Sort Key: activity.end_time DESC
        Sort Method: top-N heapsort  Memory: 27kB
        ->  Nested Loop  (cost=1.12..955.25 rows=1 width=24) (actual time=0.035..4.244 rows=447 loops=1)
              ->  Index Only Scan using tmp_index_2 on notification  (cost=0.56..326.71 rows=124 width=16) (actual time=0.017..1.039 rows=1218 loops=1)
                    Index Cond: (user_id = '9a51f675-e1e2-46e5-8bcd-6bc535c7e7cb'::uuid)
                    Heap Fetches: 689
              ->  Index Only Scan using tmp_index_1 on activity  (cost=0.56..5.07 rows=1 width=24) (actual time=0.002..0.002 rows=0 loops=1218)
                    Index Cond: ((space_id = '6d702c09-8795-4185-abb3-dc6b3e8907dc'::uuid) AND (id = notification.activity_id))
                    Heap Fetches: 1
Planning time: 0.484 ms
Execution time: 4.428 ms
关于这个查询,仍然困扰我的是
rows=1218
loops=1218
。此查询在所有读取用户通知中循环,并对活动表进行查询

我希望能够创建一个单独的索引,以模拟数据非规范化的方式读取所有这些数据。例如,如果我向通知表中添加space\u id、type和end\u time,我可以创建以下索引并以毫秒的分数进行读取

create index tmp_index_3 on notification using btree (
    user_id,
    space_id,
    end_time desc
) where (
    read = true 
    and type != 'commented'
);

目前,在Postgres中,如果不进行非规范化,这是不可能的吗?

查看您的代码,您应该使用它来筛选一个复合索引

table notification  columns  : user_id, read, activity_id


table activity columns space_id, type, id 
对于查询和订单,您还可以在活动的组合中添加结束时间

   table activity columns space_id, type, id, end_time
您还应该使用explict-inner-join-sintax

select activity.id from activity
INNER JOIN notification  ON  notification.user_id = '9a51f675-e1e2-46e5-8bcd-6bc535c7e7cb'
    and notification.read = true
    and notification.activity_id = activity.id
    and activity.space_id = '6d702c09-8795-4185-abb3-dc6b3e8907dc'
    and activity.type != 'commented'
order by activity.end_time desc
limit 20;
添加索引:

create index ix1_activity on activity (space_id, type, end_time, id);

create index ix2_notification on notification (activity_id, user_id, read);
这两个“覆盖索引”可以使您的查询非常快速


此外,如果运气好的话,它将首先读取
活动
表(仅20行),并在
通知
上执行嵌套循环联接(NLJ)。也就是说,非常有限的指数行走。

138ms(0.1秒)似乎相当快。您需要多快的速度?请回答您的问题,并为有问题的表添加
create table
语句,包括所有索引的定义。索引适用于单个表。不能跨多个表创建索引。如果138毫秒对您来说仍然太慢,那么您将需要对数据进行反规范化。您可以做的一件事是使用过滤器扩展索引
通知\u user\u id\u idx
(或创建附加索引),使用
where read
仅索引已读取的通知,这将减少索引大小并使位图索引扫描更快,因为它必须查找更少的行。与性能无关,但是:您应该停止在
WHERE
子句中使用那些陈旧、过时和脆弱的隐式联接,并开始使用现代的显式
JOIN
运算符last suggestion removedHmm。您能解释一下为什么在通知索引中包含
activity\u id
?为什么是最后一次?为什么
id
在活动索引中?似乎有点奇怪…添加活动id是为了让索引解析查询所需的所有数据..是最后一个..因为我与for filter(where子句)不太相关,因此索引包含所有信息,可以避免访问表数据。。对于索引类型,可以将此列放置在您喜欢的位置。。查看selectivit查看正确的位置Hey@scaisEdge,查看我文章中的最新编辑。我已经合并了您的索引。很明显,如果您更改数据模式并减少关系,您将提高性能,但这与只有您才能知道的应用程序ad db设计方面有关。。无论如何,我的建议似乎提高了绩效。。
select activity.id from activity
INNER JOIN notification  ON  notification.user_id = '9a51f675-e1e2-46e5-8bcd-6bc535c7e7cb'
    and notification.read = true
    and notification.activity_id = activity.id
    and activity.space_id = '6d702c09-8795-4185-abb3-dc6b3e8907dc'
    and activity.type != 'commented'
order by activity.end_time desc
limit 20;
create index ix1_activity on activity (space_id, type, end_time, id);

create index ix2_notification on notification (activity_id, user_id, read);