簡體   English   中英

具有相同WHERE子句的同一表上的兩個不同查詢

[英]Two different queries on the same table with the same WHERE clause

我有兩個不同的查詢。 但是它們都在同一個表上,並且都具有相同的WHERE子句。 因此,他們正在選擇同一行。

查詢1:

SELECT HOUR(timestamp), COUNT(*) as hits 
FROM hits_table 
WHERE timestamp >= CURDATE() 
GROUP BY HOUR(timestamp)

查詢2:

SELECT country, COUNT(*) as hits 
FROM hits_table 
WHERE timestamp >= CURDATE()
GROUP BY country

如何提高效率?

如果該表的索引正確,那么整個表有多大大小都沒關系,因為您只查看今天的行。

如果表索引不正確,無論您做什么,這些查詢的性能都會很糟糕。

您的WHERE timestamp >= CURDATE()子句意味着您需要在timestamp列上有一個索引。 在您的一個查詢中, GROUP BY country顯示(timestamp, country)的復合覆蓋索引將有很大幫助。

因此,單個復合索引(timestamp, country)將滿足您問題中的兩個查詢。

讓我們解釋一下它是如何工作的。 為了查找今天的記錄(或者實際上是任何以特定timestamp值開始和結束的記錄)並按國家/地區進行分組並計數,MySQL可以通過執行以下步驟來滿足查詢:

  1. 隨機訪問與timestamp匹配的第一條記錄的索引。 O(log n)。
  2. 從指數中獲取第一country價值。
  3. 掃描到索引中的下一個country值並計數。 上)。
  4. 重復第三步,直到timestamp范圍結束。

這項索引掃描操作的速度與一組ace開發人員(MySQL團隊)以十年的辛勤工作所能達到的速度一樣快。 (您可能無法在星期六的下午超越它們。)MySQL只需一小部分索引就能滿足整個查詢,因此它背后的表有多大並不重要。

如果您在另一個查詢之后立即運行其中一個查詢,則MySQL仍有可能在RAM緩存中保留部分或全部索引數據塊,因此它可能不必從磁盤重新獲取它們。 這將提供更多幫助。

您看到示例查詢如何以timestamp嗎? 最重要的WHERE准則選擇時間戳范圍。 這就是為什么我建議的復合索引將timestamp作為其第一列的原因。 如果沒有任何以country開頭的查詢,那么該列上的簡單索引可能就沒有用了。

您詢問是否真的需要復合覆蓋指數。 您可能應該閱讀 有關它們如何工作的信息,並自己做出決定。

選擇索引時顯然需要權衡。 每個索引都會稍微減慢INSERTUPDATE的過程,並且可以大大加快查詢的速度。 只有您才能解決您的特定應用程序的權衡問題。

由於兩個查詢具有不同的GROUP BY子句,因此它們本質上是不同的,因此無法合並。 假設timestamp字段上已經存在索引,則沒有直接的方法可以使此效率更高。

如果數據集很大(1000萬或更多行),則可以通過對country, timestamp創建額外的組合索引而獲得一些額外的效率,但這不太可能被衡量,並且通常可以通過以下方法來緩解缺少的情況:如果這兩個查詢是在另一個查詢之后直接執行的,則為MySQL本身提供內存緩沖。

暫無
暫無

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

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