【问题标题】:Query takes too long to fetch data查询需要很长时间才能获取数据
【发布时间】:2015-06-25 12:21:05
【问题描述】:

我知道查询日志很慢,但这不只是针对超过最大执行时间的查询吗?我的问题略有不同(我认为)。

我正在运行以下查询,对我来说它似乎不应该出现问题。但是当我运行它时,“运行”时间超过 20 秒,然后它就在那里“抓取”了很长时间!由于数据库性能问题,我不得不停止它。

谁能解释我在哪里出错了。编码新手,所以请温柔。

SELECT 
t1.oid,
(SELECT 
        DATE_FORMAT(t2.date,
                    '%d/%m/%y') AS 'AVF Date'
    FROM
        t2
    WHERE
        t1.oid = t2.fk_oid
            AND t2.type = '-25'
            AND YEAR(t2.date) BETWEEN 2005 AND 2014
    ORDER BY t2.date ASC
    LIMIT 1) AS 'AVF Date',
t2.site 
FROM
t1
left join t2 on t1.oid=t2.fk_oid

更新 - 好的,所以我需要如下。我们有一个患者数据库,这些患者的程序记录在该数据库中。我正在尝试返回患者 oid (t1.oid) 以及他们拥有的 FIRST 程序(如果它是在 2005 年和 2014 年之间)以及他们拥有它的位置(分别为 t2.date 和 t2.site),但前提是程序属于特定类型 (t2.type = '-25')

基本上是这样。所有在 2005 年至 2014 年间发生 AVF 的患者以及 AVF 的“部位”(在本例中为左臂/右臂等)

我希望这能让它更清楚一点。

提前致谢。

米奇

【问题讨论】:

  • 第一件事:当查询运行缓慢时,请始终对其执行EXPLAIN(并将结果添加到您的问题中)。

标签: mysql performance mysql-slow-query-log


【解决方案1】:

我觉得你可以只用join而不用select中的子查询,试试看:

SELECT t1.oid, DATE_FORMAT(t2.date,'%d/%m/%y'),t2.site
FROM table1 AS t1
LEFT JOIN table2 AS t2
ON t1.oid = t2.fk_oid
WHERE
    t2.type = '-25'
    AND YEAR(t2.date) BETWEEN 2005 AND 2014
ORDER BY t2.date ASC
LIMIT 1;

Ps:我没有测试过代码。

【讨论】:

  • 非常感谢。这工作得很快,但它为一些 oid 返回了多行,因为有不同日期的条目。如果有多个,我想返回第一个日期。这就是为什么我认为子查询会起作用。
  • 对不起,我没有理解正确,您能否再解释一下,以便我们按照您需要的方式完成它?
  • @MikeDWakelyn 尝试将 LEFT JOIN 更改为 INNER JOIN 并查看它是否返回您想要的结果。
  • 谢谢 - 它运行起来要快得多,但数据的“获取”仍然太长且资源繁重。
  • @Gregory Hart - 感谢您的编辑,我已经将 t2.site 添加到查询中。
【解决方案2】:
SELECT  a.fk_oid AS oid,
        DATE_FORMAT(a.first_date, '%d/%m/%y') AS 'AVF Date',
        GROUP_CONCAT(b.site) AS "site(s)"
    FROM  
      ( SELECT  fk_oid,
                MIN(date) AS first_date
            FROM  site
            WHERE  date >  CURDATE() - INTERVAL 10 YEAR
              AND  date <= CURDATE()
              AND t2.type = -25
            GROUP BY  fk_oid 
      ) AS a
    JOIN  site AS b
    WHERE  b.fk_oid = a.fk_oid
      AND  b.date   = a.first_date ; 
  • 内部查询为每个 oid 找到 first_date
  • 外部查询获取 site,但进一步假设给定 oid 和日期可能有多个 sites
  • 性能需要INDEX(type, date)
  • 性能需要INDEX(fk_oid, date)
  • 我假设type 是一个数字,而不是一个字符串。
  • 我重写了日期比较以暗示“过去 10 年”。如果没有未来的行,获取AND date &lt;= CURDATE() 的id。
  • 因为你似乎只需要oid,所以我去掉了t1。如果您需要 t1 中的更多字段,请添加 JOIN t1 WHERE t1.oid = a.fk_oid 并引用所需的字段。

(我正在删除我的另一个答案。)

【讨论】:

  • 感谢大家的回答。有帮助!