使用索引跨兩個表進行性能調整?
假設我有兩個表和一個這樣的 SQL 查詢
SELECT table_a.*, table_b.* FROM table_a, table_b WHERE table_a.id = ? AND table_b.col_x = table_a.col_x AND table_b.id = table_a.id;
將 SQL 查詢重寫為 JOIN 是否會提高性能?
SELECT table_a.*, table_b.* FROM table_a JOIN table_b on (table_b.id = table_a.id AND table_b.col_x = table_a.col_x) WHERE table_a.id = ?;
假設表有這些目前索引
--table_a create index table_a_index_z_id on table_a (col_z, id); --table_a create index table_a_index_x on table_a (col_x); --table_b create index table_b_index_id on table_b (id);
如果有的話,還有哪些額外的索引可以提高上述查詢的性能?
編輯
表的主鍵是
alter table table_a add (constraint table_a_pk primary key (id, col_b, col_x)) // there is no PK on table_b
您的實際答案將取決於您正在使用的數據庫系統。但是,一般而言,索引可能會有所幫助,具體取決於查詢優化器的複雜程度。
這兩個查詢在技術上是相同的。一種使用舊的 SQL 格式(SQL-89?)進行連接,而另一種使用 SQL-92 中的顯式 JOIN 語句。但是,由於優化器的差異,第二種形式可能會為您提供更好的性能。
此外,它更具可讀性,並且對於某些複雜的查詢,舊形式的 LEFT 和 RIGHT JOIN 等價物可能會導致不正確的輸出。由於在某些數據庫引擎(包括更高版本的 SQL Server)中也不允許使用它們,因此始終使用 SQL-92 格式,而不是使用舊形式的內部聯接和 LEFT、RIGHT(如果實施,則使用 CROSS 和 FULL OUTER) JOIN 使用顯式形式可能會造成混淆。強烈建議使用 SQL-92 中的顯式連接語法。
連接這兩個表所需的索引不是最理想的。對您來說最有效的索引樣式將在兩個表上都有一個索引
id
,col_x
因為這兩個欄位都在表 JOIN 中使用。但是,這可能會因儲存在兩個表中的實際數據而異。例如,如果
table_b
只包含幾十條記錄(加減,取決於記錄大小,實際使用的數據庫系統,磁碟和記憶體的速度等),那麼系統可能會選擇掃描表以查找匹配項,無論索引是什麼之所以創建,僅僅是因為對這麼小的表進行表掃描比在索引中查找行,然後在磁碟上查找行來讀取它更有效。但是,一般來說,我上面談到的索引是最有效的。所以現在你明白了為什麼在數據庫中建立索引是一門藝術,儘管它的邏輯很簡單。現實世界中還有其他考慮因素。歡迎來到 DBA 體驗的世界!
您的第一個查詢也是一個 JOIN,僅使用“舊”ANSI-89 語法,而不是 ANSI-92 中引入的顯式 JOIN 子句。
大多數 DBMS 應該將這兩個查詢視為等效,但您應該通過執行這兩個查詢並檢查執行計劃來檢查您的特定引擎。
關於索引,我建議您在 (id, col_x) 上為兩個表嘗試複合索引。我也會嘗試在 WHERE 子句中添加一個謂詞:
WHERE table_a.id = ? AND table_b.id = ?
儘管這在邏輯上是冗餘的,並且不會更改輸出,因為連接已經過濾掉了 id 不相同的行,但一些查詢優化器傾向於在謂詞是顯式而不是隱含的情況下更好地使用索引,因為它們缺乏邏輯來推斷。檢查執行計劃,你就會知道。
節日快樂!