Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.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 - Fatal编程技术网

查询执行不佳(嵌套联接、横向联接)(PostgreSQL)

查询执行不佳(嵌套联接、横向联接)(PostgreSQL),sql,postgresql,Sql,Postgresql,我正在处理一个涉及四个表的查询。模式在以下ER模型中绘制: 我正在尝试编写一个查询,以返回其文件大小总和不超过关联计划存储限制的所有站点。换句话说,我想知道一旦有可用的存储空间,哪些网站能够创建新文件 诀窍在于,一个合同计划可以有多个站点,这些站点可以有多个文件,因此一旦一个站点超过限制,共享同一合同计划的所有站点也必须被禁用 经过多次尝试,我得到了以下SQL: SELECT sites FROM plans AS p INNER JOIN ( SELECT cp.plan_id AS pl

我正在处理一个涉及四个表的查询。模式在以下ER模型中绘制:

我正在尝试编写一个查询,以返回其文件大小总和不超过关联计划存储限制的所有站点。换句话说,我想知道一旦有可用的存储空间,哪些网站能够创建新文件

诀窍在于,一个合同计划可以有多个站点,这些站点可以有多个文件,因此一旦一个站点超过限制,共享同一合同计划的所有站点也必须被禁用

经过多次尝试,我得到了以下SQL:

SELECT sites
FROM plans AS p
INNER JOIN (
  SELECT cp.plan_id AS plan_id, cp.id AS contracted_plan_id, array_agg(s.id) AS sites, SUM(total_size) AS total
  FROM contracted_plans AS cp
  INNER JOIN sites AS s ON cp.id = s.contracted_plan_id
  LEFT JOIN LATERAL(
    SELECT SUM(size) AS total_size
    FROM files AS f
    WHERE f.site_id = s.id
  ) AS agg ON TRUE
  GROUP BY cp.id, cp.plan_id
) AS total_per_contracted_plan
ON p.id = total_per_contracted_plan.plan_id
WHERE total < p.storage_limit;
目前这个SQL似乎正在工作,但我注意到它的性能不太好

我在数据库中填充了大约200000个合同计划、200000个站点(每个合同计划一个站点)和大约3kk个文件(每个站点15个文件)。只有5个计划,所以我将每个合同计划关联到一个随机计划

所有的PK和FK都有索引。我正在使用PostgreSQL,最新版本

执行解释分析时,我得到以下信息:。几乎用了4秒才完成,这似乎太过分了

如何提高SQL的性能?

Fiddle-


你能把一些样本数据和预期结果放在一起吗?也许是sqlfiddle@BrianDeMilia哇,这个sqlfiddle对我来说是新的。我们开始:。我已经尝试了您的示例,看起来它的执行速度比我当前的示例慢:查询计划|执行时间:9745.299ms@andrielfn请尝试修改sql,请参阅fiddle
select distinct site_id
  from (select s.id as site_id,
               p.id as plan_id,
               p.storage_limit,
               sum(f.size) over(partition by s.id) as tot_site
          from sites s
          join files f
            on f.site_id = s.id
          join contracted_plans cp
            on cp.id = s.contracted_plan_id
          join plans p
            on p.id = cp.plan_id) x
 where tot_site < storage_limit