本文將介紹如何在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及以上版本。