微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PostgreSQL 13 中的查询优化

如何解决PostgreSQL 13 中的查询优化

问题:

sql QUERY:需要可以访问内容 (contenidos) 的用户 (cuenta_usuario) 的姓名 ("nombre") 和电子邮件 ("e_mail") 评分(“valoracion”)超过 5 并且有电影(peliculas)的持续时间(“duracion”)在 90 到 100 分钟或系列(系列)少于 6 个季节(“temporadas”)或多于 15 个 章节(“capitulos”);并且这些用户可以看到超过 3 个相关流派 (generos) 在前 7 个中至少支付了一次付款 (pago) 五月天

我需要针对 Netflix 数据库优化以下查询,因为它从不显示结果。我在同一个数据库中用较少的行尝试了相同的查询,它工作得很好,但原始数据库有超过 20.000.000 行,它从不显示结果。这是查询

select "nombre","e_mail" from cuenta_usuario
-- Inner join cuenta_usuario --> pago
inner join (select "ID_cuenta_usuario","suscripcion_ID_suscripcion" from pago 
            where "fecha">'2020-05-01' and "fecha"<'2020-05-07')
            AS "P" on "ID"="ID_cuenta_usuario" 
            -- Inner join pago --> suscripción
            inner join (select "suscripcion_ID" from suscripcion)
            as "S" on "P"."suscripcion_ID_suscripcion"="S"."suscripcion_ID"
            -- Inner join suscripción --> suscripción_contenidos
            inner join (select "suscripcion_ID_suscripcion","producto_ID_contenidos" from suscripcion_contenidos)
            as "SC" on "S"."suscripcion_ID"="SC"."suscripcion_ID_suscripcion"
            -- Inner join suscripción_contenidos --> contenidos
            inner join (select "producto_ID" from contenidos
                       where "valoracion">5)
                       as "C" on "SC"."producto_ID_contenidos"="C"."producto_ID"
                       -- Inner join contenidos --> peliculas y series
                       inner join (select peliculas."producto_ID_contenidos" as "pelPID",series."producto_ID_contenidos" as "serPID" from peliculas,series
                                where ("duracion" between 90 and 100) or ("temporadas"<6 or "capitulos">15) 
                                        and peliculas."producto_ID_contenidos"=series."producto_ID_contenidos")
                                as "PS" on "C"."producto_ID"="producto_ID_contenidos"
                                -- Inner join contenidos --> genero_contenidos
                                inner join(select "producto_ID_contenidos" as "gcPID","genero_ID_genero" as "generos" from genero_contenidos)
                                as "GC" on "C"."producto_ID"="GC"."gcPID"
                                -- Inner join genero_contenidos --> genero
                                inner join(select "genero_ID" as "gID" from genero)
                                as "G" on "GC"."generos"="G"."gID"
                                -- Agrupamos resultado en función del nombre y el e_mail de los usuarios
                                group by "nombre","e_mail"
                                -- Debe tener contenidos con más de 3 géneros asociados
                                having count (distinct("gID"))>3

DB的模型如下: BD model (if this helps)

我尝试添加索引之类的东西,但 Postgrest 只使用了我创建的一些索引。 Postgres 估计的查询计划如下:

"GroupAggregate  (cost=1152464845530975390662656.00..1463024484904095765757952.00 rows=666667 width=40)"
"  Group Key: cuenta_usuario.nombre,cuenta_usuario.e_mail"
"  Filter: (count(disTINCT genero.""genero_ID"") > 3)"
"  ->  Gather Merge  (cost=1152464845530975390662656.00..1444235556551140296359936.00 rows=2505190447060735695519744 width=72)"
"        Workers Planned: 2"
"        ->  Sort  (cost=1152464845530975390662656.00..1155074418913330384076800.00 rows=1043829352941973206466560 width=72)"
"              Sort Key: cuenta_usuario.nombre,cuenta_usuario.e_mail"
"              ->  Hash Join  (cost=52617333935284.70..8212401427811531751424.00 rows=1043829352941973206466560 width=72)"
"                    Hash Cond: (genero_contenidos.""genero_ID_genero"" = genero.""genero_ID"")"
"                    ->  Parallel Hash Join  (cost=52617333935283.25..4891719298764879429632.00 rows=1043829352941973206466560 width=45)"
"                          Hash Cond: (pago.""suscripcion_ID_suscripcion"" = suscripcion.""suscripcion_ID"")"
"                          ->  Merge Join  (cost=9825389.26..594642346.41 rows=38982692229 width=55)"
"                                Merge Cond: (pago.""suscripcion_ID_suscripcion"" = suscripcion_contenidos.""suscripcion_ID_suscripcion"")"
"                                ->  Sort  (cost=440627.45..440953.26 rows=130324 width=45)"
"                                      Sort Key: pago.""suscripcion_ID_suscripcion"""
"                                      ->  Parallel Hash Join  (cost=56908.40..425544.29 rows=130324 width=45)"
"                                            Hash Cond: (pago.""ID_cuenta_usuario"" = cuenta_usuario.""ID"")"
"                                            ->  Parallel Bitmap Heap Scan on pago  (cost=4266.40..363961.20 rows=130324 width=11)"
"                                                  Recheck Cond: ((fecha > '2020-05-01'::date) AND (fecha < '2020-05-07'::date))"
"                                                  ->  Bitmap Index Scan on arbol_fecha  (cost=0.00..4188.21 rows=312777 width=0)"
"                                                        Index Cond: ((fecha > '2020-05-01'::date) AND (fecha < '2020-05-07'::date))"
"                                            ->  Parallel Hash  (cost=34900.33..34900.33 rows=833333 width=46)"
"                                                  ->  Parallel Seq Scan on cuenta_usuario  (cost=0.00..34900.33 rows=833333 width=46)"
"                                ->  Materialize  (cost=9384761.81..9534360.41 rows=29919720 width=10)"
"                                      ->  Sort  (cost=9384761.81..9459561.11 rows=29919720 width=10)"
"                                            Sort Key: suscripcion_contenidos.""suscripcion_ID_suscripcion"""
"                                            ->  Hash Join  (cost=1367846.01..4135564.91 rows=29919720 width=10)"
"                                                  Hash Cond: (genero_contenidos.""producto_ID_contenidos"" = suscripcion_contenidos.""producto_ID_contenidos"")"
"                                                  ->  Seq Scan on genero_contenidos  (cost=0.00..924254.28 rows=59995428 width=13)"
"                                                  ->  Hash  (cost=1184729.01..1184729.01 rows=9974000 width=21)"
"                                                        ->  Hash Join  (cost=580205.00..1184729.01 rows=9974000 width=21)"
"                                                              Hash Cond: (suscripcion_contenidos.""producto_ID_contenidos"" = contenidos.""producto_ID"")"
"                                                              ->  Seq Scan on suscripcion_contenidos  (cost=0.00..317749.00 rows=20000000 width=13)"
"                                                              ->  Hash  (cost=416569.00..416569.00 rows=9974000 width=8)"
"                                                                    ->  Seq Scan on contenidos  (cost=0.00..416569.00 rows=9974000 width=8)"
"                                                                          Filter: (valoracion > '5'::numeric)"
"                          ->  Parallel Hash  (cost=34317517658090.93..34317517658090.93 rows=1115416774205125 width=5)"
"                                ->  nested Loop  (cost=20000059362.35..34317517658090.93 rows=1115416774205125 width=5)"
"                                      ->  nested Loop  (cost=10000059362.35..845014431937.93 rows=11154167742051 width=0)"
"                                            ->  Parallel Seq Scan on series  (cost=0.00..105332.12 rows=4165512 width=17)"
"                                            ->  Bitmap Heap Scan on peliculas  (cost=59362.35..173681.57 rows=2677742 width=12)"
"                                                  Recheck Cond: (((duracion >= '90'::numeric) AND (duracion <= '100'::numeric)) OR (""producto_ID_contenidos"" = series.""producto_ID_contenidos""))"
"                                                  Filter: (((duracion >= '90'::numeric) AND (duracion <= '100'::numeric)) OR (((series.temporadas < '6'::numeric) OR (series.capitulos > '15'::numeric)) AND (""producto_ID_contenidos"" = series.""producto_ID_contenidos"")))"
"                                                  ->  BitmapOr  (cost=59362.35..59362.35 rows=2677743 width=0)"
"                                                        ->  Bitmap Index Scan on arbol_duracion  (cost=0.00..56189.85 rows=2677742 width=0)"
"                                                              Index Cond: ((duracion >= '90'::numeric) AND (duracion <= '100'::numeric))"
"                                                        ->  Bitmap Index Scan on peliculas_pk  (cost=0.00..2.37 rows=1 width=0)"
"                                                              Index Cond: (""producto_ID_contenidos"" = series.""producto_ID_contenidos"")"
"                                      ->  Seq Scan on suscripcion  (cost=0.00..2.00 rows=100 width=5)"
"                    ->  Hash  (cost=1.20..1.20 rows=20 width=32)"
"                          ->  Seq Scan on genero  (cost=0.00..1.20 rows=20 width=32)"

Query plan in JSON format

我还尝试了一些其他类型的优化:

set constraint_exclusion = on; 
set cursor_tuple_fraction = 1.0; 

但没有一个工作正常。问题可能是查询的编写方式,或者我应该添加其他类型的修改。希望你能帮我解决这个问题。谢谢!

Other Information that might be useful

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?