如何解决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)"
我还尝试了一些其他类型的优化:
set constraint_exclusion = on;
set cursor_tuple_fraction = 1.0;
但没有一个工作正常。问题可能是查询的编写方式,或者我应该添加其他类型的修改。希望你能帮我解决这个问题。谢谢!
Other Information that might be useful
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。