全部產品
Search
文件中心

PolarDB:如何高效使用IN查詢

更新時間:Jul 06, 2024

本文將介紹如何在PolarDB-X中做IN查詢時,選擇最佳的Values個數。

功能介紹

實際情境中經常需要根據一些常量指標做IN查詢,其中IN的欄位是分區鍵。例如在電商情境中,所有訂單都會記錄到訂單表Order,此表按照訂單ID進行拆分,一個買家經常會根據已購買的訂單列表,查詢這些訂單的具體資訊。假設使用者已購買的訂單數是2,那麼會產生2個值的IN條件查詢,理論上查詢會路由到兩個2分區。查詢SQL樣本:

SELECT * FROM ORDER WHERE ORDER_ID IN (id1,id2)

隨著使用者購買的訂單數增加,查詢訂單資訊的IN值數量也會增加,這樣一次查詢很可能會路由到所有的分區,導致RT變高。下圖展示了IN值數量、掃描分區數和RT之間的關係。

052601

為了儘可能避免隨著IN值數量增加,導致物理SQL膨脹和掃描壓力,PolarDB-X在核心版本5.4.8-16069335(包含)之後引入了基於IN值做動態分區裁剪的能力。

繼續以上述情境為例假設Order表分區數量是128,IN查詢的數量128個,那麼一次查詢的SQL為:

SELECT * FROM ORDER WHERE ORDER_ID IN (id1,id2,id3....id128)

如果ID足夠離散,可能會分散到所有的分區,需要查詢最多128個分區,每個分區的物理查詢沒有做IN值的裁剪,每個物理查詢都會攜帶128個IN值條件下推給MySQL,過多的IN條件也會加大MySQL執行壓力。查詢樣本如下:

SELECT * FROM ORDER WHERE ORDER_ID_1 IN (id1,id2,id3....id128);
SELECT * FROM ORDER WHERE ORDER_ID_2 IN (id1,id2,id3....id128);
SELECT * FROM ORDER WHERE ORDER_ID_3 IN (id1,id2,id3....id128);
.....
SELECT * FROM ORDER WHERE ORDER_ID_128 IN (id1,id2,id3....id128);

在支援IN分區裁剪的版本上,首先計算層會根據條件計算分區,引入IN值的動態分區裁剪,下發給MySQL的物理查詢上就會只包含屬於該分區的ID條件,裁剪掉了多餘的IN值條件,因此IN查詢的RT和吞吐都會有一定的提升。查詢樣本如下:

SELECT * FROM ORDER WHERE ORDER_ID_1 IN (id1);
SELECT * FROM ORDER WHERE ORDER_ID_2 IN (id2,id12);
SELECT * FROM ORDER WHERE ORDER_ID_3 IN (id3,id4,id5);
.....
SELECT * FROM ORDER WHERE ORDER_ID_32 IN (id100....id128);

另外,PolarDB-X內部針對跨分區的查詢會有一個Parallel Query執行,例如涉及32個分區,針對每個使用者查詢,會有節點CPU核心數大小的並發度,例如分布式下單個節點規格為16core時,預設並發數就是16個,即32個分區會分成2批才能執行完成。

結合以往經驗,在IN查詢的業務中,阿里雲建議:
  • IN的值的數目遠小於分區數,這樣可以避免每次都做全分區查詢;
  • IN的值的數目不會隨著業務的發展而增長,這樣可以避免隨著業務變化而導致效能下降;
  • 兼顧RT和吞吐的話,建議IN的值的數量在8~32之間。

滿足上述最佳經驗後,涉及到IN查詢的業務可以做到面向並發情境下的線性擴充,而RT也不會有明顯抖動。線性擴充舉例:例如分布式16core能跑1萬個IN並發,擴充到32core之後就能跑2萬個並發。

052602

比對測試

在兼顧RT和吞吐的情境下,確定合理的IN查詢的值的數量。在規格2×16C64G的節點,針對一張分表數量為64,分表記錄數為百萬層級的表在不同值數量、不同並發下做測試。在核心版本5.4.8-16069335(包含)之後針對IN查詢進一步完善了動態裁剪分表的能力,下發的物理SQL也會裁剪掉多餘的Values,下面是比對測試的結果。

  1. 在不同並發下,不同Values值數量下測試,開啟IN查詢動態裁剪能力下,查看RT變化。052603
  2. 在不同並發下,不同Values值數量下測試,開啟IN查詢動態裁剪能力下,查看吞吐變化。052604
  3. 在不同並發下,不同Values值數量下測試,關閉IN查詢動態裁剪能力下,查看RT變化。052604
  4. 在不同並發下,不同Values值數量下測試,關閉IN查詢動態裁剪能力下,查看吞吐變化。052605
通過測試對比,可以得到以下結論:
  • 兼顧RT和吞吐時,建議IN的值的數量在8~32之間,基本對齊分布式Parallel Query的預設並發度(單節點的CPU核心數)。
  • 在核心版本5.4.8-16069335(包含)之後,在開啟IN查詢的動態裁剪能力下,吞吐和RT都有明顯的優勢,推薦您將核心版本升級至5.4.8及以上版本。