将当前行与上一行进行比较时,查询速度太慢

时间:2016-07-27 21:47:44

标签: mysql performance join compare row

当从当前行中减去前一行时,查询速度太慢,是否有更有效的方法来执行此操作? 我正在尝试创建一个数据过滤器,它能够突出显示顺序发生的事件。我有一张机器操作数据'源'表,按时间顺序排序。使用WHERE子句我过滤掉与此特定分析不太相关的数据。其余数据将插入到“已过滤”的新表中。使用来自'source'的插入的ID号,我将每一行与其前一行进行比较以找出值的差异 - 如果差值为1,则事件按顺序发生,如果差异为null,则它们没有。我的问题是将行与前一行进行比较所需的时间长度。根据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到1千万行之间。数据库将创建并使用大约50个表。该数据库被用作模拟软件的后端引擎,该软件无法处理这一数据量并对数据所代表的系统进行适当的分析。 我花了一些时间在这个问题上并遇到了以下问题; find_seq表可能是使用myISAM创建的,并且需要转换为innoDB表。我试图将默认引擎设置为innoDB,但没有看到明显的差异。 这个问题在查询慢MySQL query painfully slow on large data的问题上是类似的 - 但它的问题在于在where子句中有一个函数 - 从我的动作输出我可以看到where子句不是太慢。 我很感激任何人可能对此有任何意见。此外,我不是MySQL的熟练用户,所以如果可能的话给出详细信息。 亲切的问候。

1 个答案:

答案 0 :(得分:0)

您可以使用类似此模板的内容来识别顺序&#34;岛屿&#34;没有自我加入:

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)应该是两个岛的情况,基于未由单个值定义的序列)。

您可以进一步采用此模板,以识别&#34; island&#34;通过简单地将上述查询作为子查询来实现边界和大小:

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