2015-02-24 52 views
1

我試圖在下面的(製作)示例中說明問題。基本上,我想根據輔助表中的內容過濾主表中的記錄。當我嘗試使用子查詢時,我們的應用程序性能受到了很大沖擊(有些查詢速度減慢了近10倍)。改善子查詢性能下降的建議

在這個例子中,我想回到所有案例說明了一個客戶,除了有詳細表到產品1111和2222引用的:

select cn.id, cn.summary from case_notes cn 
where customer_id = 2 
and exists (
    select 1 from case_note_details cnd 
    where cnd.case_note_id = cn.id 
    and cnd.product_id not in (1111,2222) 
) 

我使用連接以及嘗試:

select distinct cn.id, cn.summary from case_notes cn 
join case_note_details cnd 
    on cnd.case_note_id = cn.id 
    and cnd.product_id not in (1111,2222) 
where customer_id = 2 

在這兩種情況下,執行計劃顯示兩個聚集索引掃描。任何其他方法或調整建議,以提高性能?

模式:

CREATE TABLE case_notes 
    (
    id int primary key, 
    employee_id int, 
    customer_id int, 
    order_id int, 
    summary varchar(50) 
    ); 

CREATE TABLE case_note_details 
    (
    id int primary key, 
    case_note_id int, 
    product_id int, 
    detail varchar(1024) 
    ); 

的樣本數據:

INSERT INTO case_notes 
(id, employee_id, customer_id, order_id, summary) 
VALUES 
(1, 1, 2, 1000, 'complaint1'), 
(2, 1, 2, 1001, 'complaint2'), 
(3, 1, 2, 1002, 'complaint3'), 
(4, 1, 2, 1003, 'complaint4'); 

INSERT INTO case_note_details 
(id, case_note_id, product_id, detail) 
VALUES 
(1, 1, 1111, 'Note 1, order 1000, complaint about product 1111'), 
(2, 1, 2222, 'Note 1, order 1000, complaint about product 2222'), 
(3, 2, 1111, 'Note 2, order 1001, complaint about product 1111'), 
(4, 2, 2222, 'Note 2, order 1001, complaint about product 2222'), 
(5, 3, 3333, 'Note 3, order 1002, complaint about product 3333'), 
(6, 3, 4444, 'Note 3, order 1002, complaint about product 4444'), 
(7, 4, 5555, 'Note 4, order 1003, complaint about product 5555'), 
(8, 4, 6666, 'Note 4, order 1003, complaint about product 6666'); 

回答

2

你有一個聚集索引掃描,因爲你不是它的ID,但通過非索引列訪問您case_note_details表。

我建議在case_note_id,product_id上的case-note_details表中添加一個索引。

如果您總是通過case_note_id訪問case_note_details,那麼您可能還會將主鍵重構爲case_note_id,detail_id。不需要將獨立ID作爲從屬記錄的主鍵。這將使您可以重新使用您的詳細主鍵索引來與頭表進行連接。

編輯:在customer_id上添加一個索引以及case_notes表,如Manuel Rocha建議的那樣。

+0

在case_note_id,product_id上添加缺少的索引後,我發現我仍然在show plan中獲得聚簇索引掃描,但性能確實提高了。 – 2015-02-24 20:36:22

0

你嘗試 「在」,而不是 「存在」。這有時表現不同:

select cn.id, cn.summary from case_notes cn 
where customer_id = 2 
and cn.id in (
    select cnd.case_note_id from case_note_details cnd 
    where cnd.product_id not in (1111,2222) 
) 

當然,檢查索引。

1

當使用 「存在」 我一直限制的結果與 「TOP」 波紋管:

select cn.id 
     ,cn.summary 
from case_notes as cn 
where customer_id = 2 
and  exists (
      select TOP 1 1 
      from case_note_details as cnd 
      where cnd.case_note_id = cn.id 
      and  cnd.product_id not in (1111,2222) 
) 
1

在表case_notes創建索引CUSTOMER_ID和表case_note_details創建索引case_note_idcase_note_id

然後嘗試執行這兩個查詢。現在應該有更好的表現。

也試試這個查詢

select 
    cn.id, 
    cn.summary 
from 
    case_notes cn 
where 
    cn.customer_id = 2 and 
    cn.id in 
    (
     select 
      distinct cnd.case_note_id 
     from 
      case_note_details cnd 
     where 
      cnd.product_id not in (1111,2222) 
    )