2016-07-27 114 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

相關問題