簡體   English   中英

MySQL,返回X小時內的所有測量和結果

[英]MySQL, return all measurements and results within X last hours

這個問題與我之前的問題非常相關: MySQL,在過去幾小時內返回X內的所有結果 ,另外還有一個重要的約束:

現在我有2個表,一個用於測量,一個用於部分測量的分類結果。

測量結果不斷到達,結果是在新測量分類后不斷添加。

結果不一定以測量的到達和存儲順序的相同順序存儲!

我只對介紹最后的結果感興趣。 最后我的意思是將最后一次可用結果的最大時間(時間是測量結構的一部分) 稱為Y和X秒的范圍,並將測量結果與Y和YX范圍內的可用結果一起呈現。 。

以下是2個表的結構:

事件表:

CREATE TABLE `event_data` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `Feature` char(256) NOT NULL,
  `UnixTimeStamp` int(10) unsigned NOT NULL,
  `Value` double NOT NULL,

  KEY `ix_filter` (`Feature`),
  KEY `ix_time` (`UnixTimeStamp`),
  KEY `id_index` (`id`)
) ENGINE=MyISAM

分類結果表:

CREATE TABLE `event_results` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `level` enum('NORMAL','SUSPICIOUS') DEFAULT NULL,
  `score` double DEFAULT NULL,
  `eventId` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `eventId_index` (`eventId`)
) ENGINE=MyISAM

我不能首先查詢最后的測量時間戳,因為我想要呈現當前結果的測量結果,並且由於測量結果不斷到達,結果可能仍然不可用。

因此,我想加入兩個表使用
event_results.eventId=event_data.id並且選擇event_results.eventId=event_data.id的最大時間event_data.UnixTimeStamp as maxTime ,在我有了maxTime之后,我需要再次進行相同的操作(連接2個表)並在where子句中添加一個條件

WHERE event_data.UnixTimeStamp >= maxTime + INTERVAL -X SECOND

執行2個連接似乎效率不高只是為了實現我的要求,你有更多的ef

根據我的理解,您使用的是聚合函數MAX 這將生成一個大小為1的記錄集,這是您執行的最長時間。 因此,需要將其分解為子查詢(如您所說,嵌套選擇)。 你必須在某個時候做2個查詢。 (通過子查詢/嵌套選擇,您對上一個問題的答案中有2個查詢)。

子查詢的主要時間導致問題是在查詢的select部分中執行子查詢時,因為它在每次有行時執行子查詢,這將使查詢在結果集增長時以指數方式運行。 讓我們回答你的上一個問題並以一種可怕的,低效的方式寫下來:

SELECT timeStart, 
       (SELECT max(timeStart) FROM events) AS maxTime
FROM events
WHERE   timeStart > (maxTime + INTERVAL -1 SECOND)

對於max eventtime,這將在每次有eventTime記錄時執行select查詢。 它應該產生相同的結果,但這很慢。 這就是對子查詢的恐懼來自的地方。

它還在每一行上執行聚合函數MAX ,每次都會返回相同的答案。 因此,您執行該子查詢ONCE而不是每行。

但是,對於上一個問題的答案, MAX子查詢部分運行一次,並用於過濾選擇運行一次的位置。 因此,總共運行了2個查詢。

2超快速查詢比1超級慢查詢更快跑了一個超慢。

我不完全確定你想要返回什么結果集,所以我將做一些假設。 請隨意糾正我所做的任何假設。

聽起來(對我而言)就像你希望event_data中的所有行都在絕對“最新”時間戳的一小時(或多秒)內,以及這些行,你還希望從event_results返回任何相關的行,如果任何匹配的行都可用。

如果是這種情況,那么使用內聯視圖來檢索時間戳的最大值是要走的路。 (該操作將非常高效,因為查詢將返回單行,並且可以從現有索引中有效地檢索它。)

由於您需要指定時間段內的所有行(從“最新時間”返回“最新時間減去X秒”),我們可以繼續計算同一查詢中句點的起始時間戳。 在這里,我們假設你想“回去”一小時(= 60 * 60秒):

SELECT MAX(UnixTimeStamp) - 3600 FROM event_data

注意:上面SELECT列表中的表達式基於定義為整數類型的UnixTimeStamp列,而不是DATETIME或TIMESTAMP數據類型。 如果列被定義為DATETIME或TIMESTAMP數據類型,我們可能會用以下內容表示:

SELECT MAX(mydatetime) + INTERVAL -3600 SECONDS

(我們可以用分鍾,小時等來指定間隔單位)

我們可以在另一個查詢中使用該查詢的結果。 要在相同的查詢文本中執行此操作,我們只需將該查詢包裝在括號中,並將其作為行源引用,就好像該查詢是實際的表一樣。 這允許我們從指定時間段內的event_data中獲取所有行,如下所示:

SELECT d.id
     , d.Feature
     , d.UnixTimeStamp
     , d.Value
  JOIN ( SELECT MAX(l.UnixTimeStamp) - 3600 AS from_unixtimestamp
           FROM event_data l
       ) m
  JOIN event_data d
    ON d.UnixTimetamp >= m.from_unixtimestamp

在這種特殊情況下,外部查詢中的UnixTimeStamp列不需要上限謂詞。 這是因為我們已經知道沒有UnixTimeStamp的值大於MAX(UnixTimeStamp),這是我們感興趣的時期的上限。

(我們可以MAX(l.UnixTimeStamp) AS to_unixtimestamp聯視圖的SELECT列表中添加一個表達式,返回MAX(l.UnixTimeStamp) AS to_unixtimestamp ,然后在外部查詢中包含AND d.UnixTimeStamp <= m.to_unixtimestamp類的謂詞,但那將是不必要地多余。)

您還指定了從event_results表返回信息的要求。

我相信你說你想要任何“可用”的相關行。 這表明(對我而言)如果event_results沒有匹配的行“可用”,您仍然希望從event_data表返回該行。

我們可以使用LEFT JOIN操作來實現這一點:

SELECT d.id
     , d.Feature
     , d.UnixTimeStamp
     , d.Value
     , r.id
     , r.level
     , r.score
     , r.eventId
  JOIN ( SELECT MAX(l.UnixTimeStamp) - 3600 AS from_unixtimestamp
           FROM event_data l
       ) m
  JOIN event_data d
    ON d.UnixTimetamp >= m.from_unixtimestamp
  LEFT
  JOIN event_results r
    ON r.eventId = d.id

由於是在沒有唯一約束eventIDevent_results表中,有一種可能性,即從event_results不止一個“匹配”行會被發現。 每當發生這種情況時, event_data表中的行將重復一次,對於來自event_results每個匹配行。

如果event_results沒有匹配的行,則仍會返回event_data的行,但是event_results表中的列設置為NULL。

為了提高性能,請從SELECT列表中刪除不需要返回的任何列,並在ORDER BY子句中選擇表達式時明智。 (添加覆蓋索引可以提高性能。)

對於如上書面聲明,MySQL是可能使用ix_time上的索引event_data表和eventId_index上的索引event_results表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM