查询运行时间太长

时间:2016-11-10 10:46:40

标签: mysql sql

我正在运行以下查询,以根据同一个表中的日期字段检索唯一的最新结果。但是当表增长时,这个查询会占用太多时间。任何改善这一点的建议都是受欢迎的。

select
    t2.*
from
    (
        select
            (
                select
                    id
                from
                    ctc_pre_assets ti
                where
                    ti.ctcassettag = t1.ctcassettag
                order by
                    ti.createddate desc limit 1
            ) lid
        from
            (
                select
                    distinct ctcassettag
                from
                    ctc_pre_assets
            ) t1
    ) ro,
    ctc_pre_assets t2
where
    t2.id = ro.lid
order by
    id

我们的可能包含多次相同的行,但每行都有不同的时间戳。我的对象基于单个列,例如assettag我想为每个具有最新时间戳的资产标签检索单行。

3 个答案:

答案 0 :(得分:0)

从那时起,嵌套查询总是比传统查询花费更长的时间。你可以在查询开头追加'解释'并将结果放在这里吗?这将有助于我们分析需要更长时间响应的确切查询/表。

检查表是否有索引。不建议使用未缩进的表(除非明显要求不缩进),并且在执行查询时速度非常慢。

相反,我认为最好的情况是避免完全编写嵌套查询。 Bette,分别运行每个查询,然后在第二个查询中使用结果(以数组或列表格式)。

答案 1 :(得分:0)

首先,您应该至少问自己一些问题,但也许还会给我们一个答案来提高答案的准确性:

  1. 您的数据是否已正常化?如果是,也许您应该例外以避免这种残酷的子查询问题
  2. 您使用的是索引吗?如果是,哪些,你是否充分利用它们?
  3. 一些提高查询可读性和性能的建议:   - 使用连接   - 使用分组依据   - 使用聚合器

    示例(未经测试,可能不起作用,但应该给人留下印象):

     SELECT t2.*
     FROM (
        SELECT id 
        FROM ctc_pre_assets 
        GROUP BY ctcassettag 
        HAVING createddate = max(createddate) 
        ORDER BY ctcassettag DESC 
     ) ro
     INNER JOIN ctc_pre_assets t2 ON t2.id = ro.lid
     ORDER BY id
    

    使用规范化是很好的,但有一些注意事项,规范化造成的危害大于好处。这看起来像这样的情况,但没有你的桌子在我面前,我无法确定。

    使用与你一样的方式,我不禁感觉你可能得不到所有相关的结果 - 也许其他人可以确认或否认这个?

    不是子查询都不好,但如果写错了,它们往往会造成大规模的可扩展性问题。确保以正确的方式使用它们(google it?)

    索引可以为您节省大量时间 - 如果您实际使用它们。设置它们是不够的,您必须创建实际使用索引的查询。谷歌这也是。

答案 2 :(得分:0)

找到每个ctcassettag的最新日期然后再加入以找到匹配的整行,这样更简单,也可能更快。

这假设没有ctcassettag包含多个具有相同createddate的行,在这种情况下,可以每个ctcassettag返回多行。

SELECT
    ctc_pre_assets.*
FROM
    ctc_pre_assets
INNER JOIN
(
    SELECT
        ctcassettag,
        MAX(createddate)   AS createddate
    FROM
        ctc_pre_assets
    GROUP BY
        ctcassettag
)
   newest
       ON  newest.ctcassettag = ctc_pre_assets.ctcassettag
       AND newest.createddate = ctc_pre_assets.createddate
ORDER BY
    ctc_pre_assets.id

编辑:处理具有相同日期的多行。

如果同一ctcassettag的多个行属于同一createddate,您实际上并未说明如何选择所需的行。因此,此解决方案只选择idduplicates中最低SELECT ctc_pre_assets.* FROM ctc_pre_assets WHERE ctc_pre_assets.id = ( SELECT lookup.id FROM ctc_pre_assets lookup WHERE lookup.ctcassettag = ctc_pre_assets.ctcassettag ORDER BY lookup.createddate DESC, lookup.id ASC LIMIT 1 ) 的行。

ORDER BY

这仍然使用相关的子查询,它比简单的嵌套子查询(例如我的第一个答案)慢,但它确实处理了使用"重复"。

您可以通过更改相关子查询中的Array ( [detals] => Array ( [0] => Array ( [make] => xyx [yeardeta] => 2001 ) [1] => Array ( [model] => Array ( [0] => Test one [1] => test fix [2] => Hamour [3] => Imagica ) ) [2] => Array ( [make] => xyx [yeardeta] => 2002 ) [3] => Array ( [model] => Array ( [0] => Test Two ) ) ) ) 来更改要选择的行的规则。

它也与您自己的查询非常相似,但只需少一次加入。