2015-02-24 62 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) 
    )