【问题标题】:Optimization of SQL with subquery and Having用子查询和Having优化SQL
【发布时间】:2016-07-13 00:54:55
【问题描述】:

目前我们正在使用自定义 CI 库从作为我们数据库中的数据库记录存在的文档生成 PDF 文件。

每个文档都与具有一对多关系的内容(== 行)相关。每行都有一个数字(字段:row_span),表示在 PDF 中打印后将使用多少行。

每个生成的 PDF 页面,仅使用子查询选择该页面所需的行:

$where = $this->docType."_id = ".$this->data['doc']->id." AND visible = 1";
$sql = "SELECT *,

    (SELECT
    sum(row_span) FROM app_".$this->docType."_rows X
    WHERE X.position <= O.position 
    AND ".$where." 
    ORDER BY position ASC) 'span_total'

    FROM app_".$this->docType."_rows O 
    WHERE ".$where."
    HAVING span_total > ".(($i-1)*$this->maxRows)." AND span_total <= ".($i*$this->maxRows)." ORDER BY O.position ASC ";

$rows = $rows->query($sql);

在代码中$i 是页码,$this-&gt;maxRows 是从文档模板记录中加载的,该记录指示 PDF 模板有多少可用行。

因此,当 SQL 呈现时,ID 为 834 的订单的第 1 页可能如下所示:

SELECT `app_order_rows`.*, 
(SELECT SUM(`app_order_rows_subquery`.`row_span`) AS row_span
    FROM `app_order_rows` `app_order_rows_subquery`
    WHERE `app_order_rows_subquery`.`position` <= 'app_order_rows.position'
    AND `app_order_rows_subquery`.`order_id` =  834
    AND `app_order_rows_subquery`.`visible` =  1
    ORDER BY `app_order_rows_subquery`.`position` asc) AS span_total 
FROM (`app_order_rows`) 
WHERE `app_order_rows`.`order_id` =  834
AND `app_order_rows`.`visible` =  1
HAVING span_total >  0
AND span_total <=  45
ORDER BY `app_order_rows`.`position` asc

使用 EXPLAIN 运行它会得到输出:

+====+=============+=========================+======+===============+======+=========+======+======+=============================+===+
| id | select_type | table                   | type | possible_keys | key  | key_len | ref  | rows | Extra                       |   |
+====+=============+=========================+======+===============+======+=========+======+======+=============================+===+
| 1  | PRIMARY     | app_order_rows          | ALL  | NULL          | NULL | NULL    | NULL | 1809 | Using where; Using filesort | 1 |
+----+-------------+-------------------------+------+---------------+------+---------+------+------+-----------------------------+---+
| 2  | SUBQUERY    | app_order_rows_subquery | ALL  | NULL          | NULL | NULL    | NULL | 1809 | Using where                 | 2 |
+====+=============+=========================+======+===============+======+=========+======+======+=============================+===+

这很好用,但是...当我们有大订单或发票时,它会使文档变得非常慢。这可能是由于子查询。

有没有人知道如何在没有子查询的情况下进行相同的选择?也许我们将不得不采用一种全新的方法来选择行并构建 PDF。我们欢迎建议^^

提前致谢

------------------- 编辑 --------------- ---------------

索引创建后的解释:

+====+=============+=========================+=======+===============+============+=========+=======+======+=============+===+
| id | select_type | table                   | type  | possible_keys | key        | key_len | ref   | rows | Extra       |   |
+====+=============+=========================+=======+===============+============+=========+=======+======+=============+===+
| 1  | PRIMARY     | app_order_rows          | ref   | index_main    | index_main | 5       | const | 9    | Using where | 1 |
+----+-------------+-------------------------+-------+---------------+------------+---------+-------+------+-------------+---+
| 2  | SUBQUERY    | app_order_rows_subquery | range | index_main    | index_main | 10      | NULL  | 1    | Using where | 2 |
+====+=============+=========================+=======+===============+============+=========+=======+======+=============+===+

【问题讨论】:

  • 您能否将其发布为 SQL 查询,这样我们就不必在脑海中解析您的 PHP 了?你能执行这条 SQL 并得到一个 EXPLAIN,这样我们就可以看到真正的问题是什么?您能否发布一个架构,以便我们查看您是否已经有任何索引?
  • 大部分是 SQL :) 我将在下次休息时更新问题:D
  • '...它使文档变得非常慢。这可能是由于子查询。您是否监控了这种行为,或者您只是在猜测?
  • @Philipp 我读它是为了寻找可能的原因。
  • @NevilleK 我做了更新并添加了一些东西。

标签: php mysql codeigniter


【解决方案1】:

正如您在 cmets 中确认的,这些表没有索引。

直接的解决方案是:

create index index_main on app_order_rows (order_id, position);

【讨论】:

  • 我希望通过简单的索引创建来解决它,但事实并非如此。
  • 你能在创建索引后发布 EXPLAIN 吗?
  • 我将其添加到问题中。
  • 好的 - EXPLAIN 表明它正在使用索引;现在应该快得多。您确定问题出在 SQL 上,而不是 PHP 上吗?您能否在有和没有索引的命令行中运行查询,看看时间是多少?
  • 在这种情况下,绝对不是您应该优化的 SQL - 它是 PHP 或基础架构。 PDF 生成可能会占用大量内存 - 大型文档可能会超出 Web 服务器的内存限制?
猜你喜欢
  • 2016-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-20
  • 1970-01-01
相关资源
最近更新 更多