2016-07-27 115 views
0

当从当前行中减去前一行时,查询速度太慢,是否有更高效的方法来执行此操作? 我正在尝试创建一个数据过滤器,它有能力突出显示那些没有按顺序发生的事件。我有一张按时间顺序排列的机器运行数据“源”表。使用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到1000万行之间。该数据库将创建并使用约50个表。该数据库被用作模拟软件的后端引擎,该引擎不具备处理这些数据量的能力,并对数据所代表的系统进行适当的分析。 我在这个问题上花了一些时间,并且遇到了以下问题; find_seq表有可能是使用myISAM创建的,并且需要转换为innoDB表。我试图将默认引擎设置为innoDB,但没有看到明显的差异。 这个问题类似于其缓慢查询MySQL query painfully slow on large data的问题 - 但它的问题在于在where子句中有一个函数 - 从我的操作输出中我可以看到where子句不太慢。 我会很感激任何人都可能有此输入。此外,我不是MySQL的熟练用户,所以如果可能的话提供详细信息。 亲切的问候。

+0

上'filtered_dta'的'IDx1'可以帮助索引;但我不确定在连接中有多少“+ 1”操作。 – Uueerdo

+0

谢谢Uueerdo我添加了索引,发现查询运行速度提高了6%。尽管如此,它并没有使查询时间缩短足够多的余量。 – PhDunce

+0

@Uueerdo - 很好。但由于“LEFT”,将其改为't2.IDx1 = t1.IDx1 + 1'。 –

回答

0

您可以使用这样的模板来识别顺序“孤岛”不自联接:

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 
; 
+0

Brilliant Uueerdo - 我的3012秒查询现在需要0.218秒。你的假设是正确的 - 源'seqID'确实增加了一个。我非常感谢您的意见 - 谢谢。我的投票没有注册,因为我太小白菜了。 +1。 – PhDunce

相关问题