【问题标题】:When comparing current row with previous row the query is too slow将当前行与上一行进行比较时,查询速度太慢
【发布时间】:2016-07-27 21:47:43
【问题描述】:

当从当前行中减去前一行时,查询太慢了,有没有更有效的方法来做到这一点? 我正在尝试创建一个数据过滤器,它能够突出显示顺序发生的事件,而不是那些没有发生的事件。我有一个按时间顺序排列的机器操作数据“源”表。使用 WHERE 子句过滤掉与此特定分析不太相关的数据。剩余的数据被插入到一个“过滤”的新表中。使用从“源”中插入的 ID 号,我将每一行与其前一行进行比较,以找出值的差异——如果差异为 1,则事件已按顺序发生,如果差异为空,则它们没有。我的问题是将一行与前一行进行比较所需的时间长度。根据 MySQL Workbench 操作输出,我已将我的数据量减少到全部量的 2.5%(275000 行),查询需要 3012 秒。我尝试过以不同的方式构造查询,但最终走到了死胡同。所以我的问题是 – 有没有更有效的方法来比较一行与前一行?

好的——这里有更多细节。

/*First I create the table for the filtered data */
drop table if exists filtered_dta;
create table filtered_dta
 ( 
 ID         int (11)        not null        auto_increment,
 IDx1       int (11),
 primary key (ID)
 );

/然后我插入过滤后的数据/

insert into filtered_dta (IDx1)
      select seq from source
            WHERE   range_value < -1.75
            and     range_value > -5 ;

                   /* Then I compare each row with its previous */

                    select              t1.ID, t1.IDx1,(t1.IDx1-t2.IDx1) 
                    as                  seq_value
                    from                filtered_dta t1 
                    left outer join     filtered_dta t2 
                    on                  t1.IDx1 = t2.IDx1+1
                    order by IDx1
                    ;

这里是示例表。

Table - filtered_dta                  Results

   | ID | IDx1 |              | ID | IDx1 | seq_value |
     1     3                    1     3       null
     2     4                    2     4        1
     3     7                    3     7       null
     4    12                    4    12       null
     5    13                    5    13        1
     6    14                    6    14        1

来自源表的完整数据集预计在 3 到 1000 万行之间。该数据库将创建和使用大约 50 个表。该数据库被用作模拟软件的后端引擎,该软件没有能力处理大量数据并对数据所代表的系统进行适当的分析。 我在这个问题上花了一些时间,并遇到了以下问题; find_seq 表可能是使用 myISAM 创建的,并且需要转换为 innoDB 表。我尝试将默认引擎设置为 innoDB,但没有发现明显差异。 这个问题与慢查询MySQL query painfully slow on large data 的问题类似——但它的问题在于在 where 子句中有一个函数——从我的操作输出中,我可以看到 where 子句并不太慢。 我将不胜感激任何人对此的任何意见。另外,我不是 MySQL 的熟练用户,所以如果可能的话,请提供详细信息。 亲切的问候。

【问题讨论】:

  • filtered_dtaIDx1 上的索引可能会有所帮助;但我不确定加入中的+1 操作有多少。
  • 感谢 Uueerdo 我添加了索引,发现查询运行速度提高了 6%。尽管单独使用它并不能显着缩短查询时间。
  • @Uueerdo - 好。但是由于LEFT,将其更改为t2.IDx1 = t1.IDx1+1

标签: mysql performance join compare row


【解决方案1】:

您可以使用类似此模板的内容来识别没有自连接的连续“孤岛”:

SELECT @island := @island + IF(seqId <> @lastSeqId + 1, 1, 0) AS island
, orderQ.[fieldsYouWant]
, @lastSeqId := seqId
FROM (
   SELECT [fieldsYouWant], [sequentialIdentifier] AS seqId
   FROM [theTable] AS t
      , (SELECT @island := 0, @lastSeqId := [somethingItCannotBe]) AS init_dnr -- Initializes variables, do not reference
   WHERE [filteringConditionsMet]
   ORDER BY [orderingCriteria]
) AS orderingQ
;

我尝试使其尽可能通用,但您会注意到我必须恢复到 seqId 是数字并预计会增加 1 的假设。如果需要,island 计算中的条件可能会复杂得多(例如,(A, 1), (A, 2), (B, 3) 应该是两个岛,基于不是由单个值定义的序列)。

您可以进一步使用此模板,通过简单地将上述查询作为子查询来识别“岛”边界和大小,例如:

SELECT island, MIN(seqId), MAX(seqId), COUNT(seqId)
FROM ([above query]) AS islandQ
GROUP BY island
;

【讨论】:

  • Brilliant Uueerdo - 我的 3012 秒查询现在需要 0.218 秒。您的假设是正确的 - 源“seqID”确实增加了 1。我非常感谢您的意见 - 谢谢。我的赞成票没有登记,因为我太菜鸟了。 +1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-22
  • 1970-01-01
相关资源
最近更新 更多