本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
讀取 Aurora DSQL EXPLAIN 計劃
了解如何讀取 EXPLAIN 計劃是最佳化查詢效能的關鍵。在本節中,我們將逐步介紹 Aurora DSQL 查詢計畫的真實範例、顯示不同掃描類型的行為、說明套用篩選條件的位置,以及強調最佳化的機會。
完整掃描範例
Aurora DSQL 具有序列掃描,其功能與 PostgreSQL 和完整掃描相同。兩者之間的唯一區別在於完整掃描可以在儲存體上利用額外的篩選。因此,幾乎一律會在連續掃描上方選取。由於相似性,我們只會涵蓋更有趣的完整掃描範例。
完整掃描主要用於沒有主索引鍵的資料表。由於 Aurora DSQL 主索引鍵預設為完全涵蓋索引,因此在 PostgreSQL 會使用循序掃描的許多情況下,Aurora DSQL 很可能在主索引鍵上使用僅限索引掃描。與大多數其他資料庫一樣,沒有索引的資料表會嚴重擴展。
EXPLAIN SELECT account_id FROM transaction WHERE transaction_date > '2025-01-01' AND description LIKE '%external%';
QUERY PLAN
----------------------------------------------------------------------------------------------------------------
Full Scan (btree-table) on transaction (cost=125100.05..177933.38 rows=33333 width=16)
Filter: (description ~~ '%external%'::text)
-> Storage Scan on transaction (cost=12510.05..17793.38 rows=66666 width=16)
Projections: account_id, description
Filters: (transaction_date > '2025-01-01 00:00:00'::timestamp without time zone)
-> B-Tree Scan on transaction (cost=12510.05..17793.38 rows=100000 width=30)
該計劃顯示在不同階段套用的兩個篩選條件。transaction_date > '2025-01-01' 條件會套用至儲存層,減少傳回的資料量。條件稍後description LIKE '%external%'會在傳輸資料後,於查詢處理器中套用,使其效率降低。將更多選擇性篩選條件推送到儲存體或索引層通常會改善效能。
僅限索引掃描範例
僅索引掃描是 Aurora DSQL 中最理想的掃描類型,因為它們導致到儲存層的往返次數最少,並且可以進行最多的篩選。但是,因為您看到僅限索引掃描並不表示您擁有最佳計劃。由於可能發生的所有不同層級的篩選,仍必須注意可能發生篩選的不同位置。
EXPLAIN SELECT balance FROM account WHERE customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb' AND balance > 100 AND status = 'pending';
QUERY PLAN
-------------------------------------------------------------------------------
Index Only Scan using idx1 on account (cost=725.05..1025.08 rows=8 width=18)
Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
Filter: (balance > '100'::numeric)
-> Storage Scan on idx1 (cost=12510.05..17793.38 rows=9 width=16)
Projections: balance
Filters: ((status)::text = 'pending'::text)
-> B-Tree Scan on idx1 (cost=12510.05..17793.38 rows=10 width=30)
Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
在此計劃中,會先在索引掃描期間customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'評估索引條件 ,這是最有效率的階段,因為它會限制從儲存體讀取的資料量。儲存篩選條件 status = 'pending'會在資料讀取後,但在傳送至運算層之前套用,以減少傳輸的資料量。最後,查詢處理器篩選條件 會在資料移動後最後balance > 100執行,使其效率最低。其中,索引條件可提供最大效能,因為它會直接控制掃描的資料量。
索引掃描範例
索引掃描類似於僅限索引掃描,但它們需要呼叫 基底資料表的額外步驟。由於 Aurora DSQL 可以指定儲存篩選條件,因此可以在索引呼叫和查詢呼叫上執行此操作。
為了清楚這一點,Aurora DSQL 會將計劃顯示為兩個節點。如此一來,您可以清楚地看到新增包含資料欄對於從儲存體傳回的資料列有多少幫助。
EXPLAIN SELECT balance FROM account WHERE customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb' AND balance > 100 AND status = 'pending' AND created_at > '2025-01-01';
QUERY PLAN
----------------------------------------------------------------------------------------------------------
Index Scan using idx1 on account (cost=728.18..1132.20 rows=3 width=18)
Filter: (balance > '100'::numeric)
Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
-> Storage Scan on idx1 (cost=12510.05..17793.38 rows=8 width=16)
Projections: balance
Filters: ((status)::text = 'pending'::text)
-> B-Tree Scan on account (cost=12510.05..17793.38 rows=10 width=30)
Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
-> Storage Lookup on account (cost=12510.05..17793.38 rows=4 width=16)
Filters: (created_at > '2025-01-01 00:00:00'::timestamp without time zone)
-> B-Tree Lookup on transaction (cost=12510.05..17793.38 rows=8 width=30)
此計劃顯示篩選如何跨多個階段進行:
-
上的索引條件會及早
customer_id篩選資料。 -
上的儲存篩選條件會
status進一步縮小結果,然後再傳送至運算。 -
上的查詢處理器篩選條件
balance稍後會在傳輸後套用。 -
從基礎資料表擷取其他資料欄時
created_at,會評估 上的查詢篩選條件。
新增經常使用的資料欄,因為INCLUDE欄位通常可以消除此查詢並改善效能。
最佳實務
-
將篩選條件與索引資料欄對齊,以提早推送篩選。
-
使用 INCLUDE 資料欄允許僅限索引掃描並避免查詢。
-
將統計資料保持在最新狀態,以確保成本和資料列預估的準確性。
-
避免大型資料表上的未索引查詢,以避免昂貴的完全掃描。