【问题标题】:MySQL query is extremely long from PHPPHP 的 MySQL 查询非常长
【发布时间】:2020-12-18 11:20:19
【问题描述】:

我有一个查询在 PHPMyAdmin 中需要 0.0002 秒,如果我从 PHP 中执行则需要数百秒。这里是:

    SELECT  id, id_pages, link, childlink, url, hiddencontent, cansearch,
        (
            SELECT  p.id
                FROM  pages as p
                WHERE  pages.hiddencontent=1
                  AND  p.id_pages IS NOT NULL
                  AND  p.hiddencontent=0
                  AND  pages.id=p.id_pages
                order by  p.npp asc
                limit  1
        ) as id_firstchild
        FROM  pages

它返回大约 24k 行,我不知道为什么需要这么长时间。我的朋友在他的电脑上试过,它运行得很快,他的电脑也不是更好。我不知道这种 PHP 行为的原因,也许我应该在配置文件中进行一些更改?

【问题讨论】:

  • PHPMyAdmin 仅显示并获取少数第一行。您现在已经显示了您的 PHP 代码,但是如果您全部获取 24k 行,则获取和显示它们可能需要一些时间。为了改进未来的问题,请显示您的 PHP 代码并从带有表定义的查询中解释。
  • 请阅读此stackoverflow.com/tags/query-optimization/info。那么请edit你的问题。请记住,phpmyadmin 会附加 LIMIT 50 或类似于它运行的每个查询的内容。
  • 24k 行很多。你真的必须同时与他们一起工作吗?
  • @el-vanja 是的,我使用的脚本是为网站创建 URL,因此它需要我在表中的所有行。问题是它在某个地方运行得非常快,但在我的电脑上却不行,所以我想也许有人知道它为什么会发生
  • 您真的希望在您的页面中显示 24k 的网址吗?

标签: php mysql query-optimization


【解决方案1】:

你有两个问题:

为什么是时机?

“查询缓存”是否打开?这是它可以在 0.2 毫秒内运行的唯一方法。 (几乎可以肯定,在 1 毫秒内运行的任何重要的 SELECT 都没有运行,但在该缓存中找到了。)

而且,正如其他人指出的那样,phpmyadmin 默默地添加了一个LIMIT。然而,其他线索(主要在评论中)指向查询缓存给出异常结果。

如何加快速度。

SELECT  id, id_pages, link, childlink, url, hiddencontent, cansearch,
        if (hiddencontent = 1, NULL,   -- to avoid doing the SELECT
            ( SELECT  p.id
                FROM  pages as p
                WHERE  p.hiddencontent = 0
                  AND  outer.id = p.id_pages -- fails on NULL
                order by  p.npp asc
                limit  1
           )) as id_firstchild
    FROM  pages AS outer    -- clarify which is which

并拥有这个“复合”和“覆盖”索引:

INDEX(hiddencontent, id_pages, npp, id)

两个改进:

  • 避免在不需要时调用子查询。
  • 拥有一个允许子查询仅查看一行的索引,并且仅在索引的 BTree 中查看,因此“速度极快”。

【讨论】:

    【解决方案2】:

    当您尝试确定搜索或获取是否缓慢时,请在查询末尾使用LIMIT 1(如果有,请注释掉ORDER BY 部分)。这样,您将获得第一行,因此您将知道需要多长时间。它应该很快。

    另一个有用的信息是当您将整个查询包含在另一个查询中时,例如SELECT ...FROM (SELECT ...),在这种情况下,外部查询应该计算返回的行数。这将为您提供识别所有将被提取的行所需的总时间,但实际上并未提取它们。这有助于确定您的 SQL 查询是否编写得不好,或者只是需要获取大量数据。 (如果上述两个都走得很快,但你仍然得到一个缓慢的查询,那就是 fetch。)

    您也可以使用EXPLAIN 来查看您的性能问题是因为索引不足还是不正确。

    至于 phpmyadmin,您帖子上的第一条评论非常概括:phpmyadmin 使用 LIMIT,因此即使您的查询本身很慢,它也会运行得更快。

    【讨论】:

    • 我建议 phpmyadmin 使用LIMIT,因为它不想通过尝试向您显示一百万行来阻塞您的浏览器。此外,当有一个索引无法处理的ORDER BY 时,它必须获取所有行; LIMIT 在这种情况下影响很小。
    • @RickJames 这两种说法都是正确的。后者是我将添加到我的答案中的内容,因为有 ORDER BY 的人可能会惊讶地发现速度没有显着变化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-29
    • 2012-09-28
    • 1970-01-01
    相关资源
    最近更新 更多