使用嵌套选择优化查询

Posted

技术标签:

【中文标题】使用嵌套选择优化查询【英文标题】:optimize query with nested selects 【发布时间】:2012-07-23 05:48:06 【问题描述】:

是否可以优化以下查询? webdte.docto 是一个非常大的表,包含数百万个条目,并在所有查询列上运行索引。最终的排序顺序非常重要。

SELECT 
   id_doc,
   id_tip_doc,
   id_est_doc,
   folios.nro_fol,
   seleccionable
FROM
(
   SELECT distinct(nro_fol)
   FROM webdte.docto 
   WHERE
      id_tip_doc IN
      (
         SELECT distinct(id_tip_doc)
         FROM webdte.docto
         WHERE id_doc IN
         (
            SELECT id_doc
            FROM webdte.lib_doc
            WHERE id_lib = 37
         )
      ) AND
      id_doc IN
      (
         SELECT id_doc
         FROM webdte.lib_doc
         WHERE id_lib = 37
      )
) AS folios JOIN webdte.docto AS docs ON docs.nro_fol = folios.nro_fol
ORDER BY id_tip_doc, folios.nro_fol, id_est_doc;

对不起,这是我第一个查询方法的解释。平等主义的答案已经很好,但也许它还可以更快?谢谢!

Sort  (cost=13745.13..13805.42 rows=24115 width=22)"
  Sort Key: docs.id_tip_doc, docto.nro_fol, docs.id_est_doc"
  ->  Hash Join  (cost=9240.19..11492.84 rows=24115 width=22)"
        Hash Cond: (docto.nro_fol = docs.nro_fol)"
        ->  HashAggregate  (cost=4424.81..4665.91 rows=24110 width=6)"
              ->  Hash Semi Join  (cost=733.75..4364.54 rows=24110 width=6)"
                    Hash Cond: (docto.id_doc = lib_doc.id_doc)"
                    ->  Seq Scan on docto  (cost=0.00..2885.28 rows=105128 width=10)"
                    ->  Hash  (cost=432.38..432.38 rows=24110 width=4)"
                          ->  Seq Scan on lib_doc  (cost=0.00..432.38 rows=24110 width=4)"
                                Filter: (id_lib = 37)"
        ->  Hash  (cost=2885.28..2885.28 rows=105128 width=22)"
              ->  Seq Scan on docto docs  (cost=0.00..2885.28 rows=105128 width=22)"

【问题讨论】:

您能告诉我们 EXPLAIN 和 EXPLAIN ANALYZE 的结果吗?没有这些信息,几乎不可能优化查询,因为您看不到实际问题出在哪里。只是猜测... 【参考方案1】:

我认为你可以简化为:

SELECT id_doc
      ,id_tip_doc
      ,id_est_doc
      ,nro_fol
      ,seleccionable
FROM   webdte.docto d
WHERE  EXISTS (
   SELECT 1
   FROM   webdte.docto   d0
   JOIN   webdte.lib_doc l USING (id_doc)
   WHERE  l.id_lib = 37
   AND    d0.nro_fol = d.nro_fol
   )
ORDER  BY id_tip_doc, nro_fol, id_est_doc;

因为EXISTS,所以不需要DISTINCT。如果nro_fol 上有很多重复项,这可以大大加快查询速度。 您的原始查询非常多余。

【讨论】:

【参考方案2】:

我认为获取唯一 id_tip_doc 的 where 子句并不重要,因为无论如何您都在选择 distinct(nro_fol)。尽管优化此查询的最佳方法之一是使用正确的索引,然后重新编写查询。

您可以创建以下索引(尽管它也取决于您的其他查询): 1. webdte.lib_doc:id_lib 2. webdte.docto : id_doc + nro_fol

select id_doc,id_tip_doc,id_est_doc,  folios.nro_fol ,seleccionable 

来自(选择不同的(nro_fol) 来自 webdte.docto 在哪里 id_doc in(从 webdte.lib_doc 中选择 id_doc,其中 id_lib = 37) ) 作品集 在 docs.nro_fol = folios.nro_fol 上加入 webdte.docto 文档 按 id_tip_doc、folios.nro_fol、id_est_doc 排序;

【讨论】:

以上是关于使用嵌套选择优化查询的主要内容,如果未能解决你的问题,请参考以下文章

优化多个嵌套选择的 SQL 查询

如何优化这个嵌套的 SQL 查询

使用算术运算优化 MySQL 嵌套选择

数据库系统概念笔记——第十二章:查询处理

使用 laravel 查询生成器嵌套选择?

JavaSE选择结构——优化if-else的嵌套代码