2

我们有一个相当大的 SQL 查询,它的性能相当差。问题之一(来自分析查询计划)是我们拥有的连接数量。

本质上,我们的数据中有值,我们需要在另一个表上进行查找。以获取要显示给用户的值。问题是我们在同一个表上做了 4 次连接,因为有 4 个不同的列都需要相同的查找。

希望这张图可以更清楚

Raw_Event_data
event_id,   datetime_id,         lookup_1, lookup_2, lookup_3, lookup_4
1,          2013-01-01_12:00,    1,        5,        3,         9          
2,          2013-01-01_12:00,    121,      5,        8,         19
3,          2013-01-01_12:00,    11,       2,        3,         32
4,          2013-01-01_12:00,    15,       2,        1,         0

Lookup_table
lookup_id,      lookup_desc
1,              desc1
2,              desc2
3,              desc3
...

我们的查询看起来像这样

Select 
    raw.event_id, 
    raw.datetime_id,
    lookup1.lookup_desc,
    lookup2.lookup_desc,
    lookup3.lookup_desc,
    lookup4.lookup_desc,
FROM 
    Raw_Event_data raw, Lookup_table lookup1,Lookup_table lookup2,Lookup_table lookup3,Lookup_table lookup4
WHERE raw.event_id = 1 AND
raw.lookup_1 *= lookup1 AND
raw.lookup_2 *= lookup2.lookup_id AND
raw.lookup_3 *= lookup3.lookup_id AND
raw.lookup_4 *= lookup4.lookup_id

所以我得到了输出

 1, 2013-01-01_12:00, desc1, desc5, desc3, desc9

正如我所说,查询有效,但连接正在扼杀性能。这是我在那里给出的一个简单示例,实际上将有 12 个像上面这样的连接,我们不会选择特定事件,而是选择一系列事件。

问题是,是否有更好的方法来进行这些连接。

4

2 回答 2

0

如果我被 DBA 拒绝,我的第一次尝试是自己处理索引。

declare @start_range bigint, @end_range bigint

select
    @start_range = 5
    ,@end_range = 500

create local temporary table raw_event_subset
( --going to assume some schema based on your comments...obviously you will change these to whatever the base schema is.
    event_id bigint
    ,datetime_id timestamp
    ,lookup_1 smallint
    ,lookup_2 smallint
    --etc
) on commit preserve rows

create HG index HG_temp_raw_event_subset_event_id on raw_event_subset (event_id)
create LF index LF_temp_raw_event_subset_lookup_1 on raw_event_subset (lookup_1)
create LF index LF_temp_raw_event_subset_lookup_2 on raw_event_subset (lookup_2)
--etc

insert into raw_event_subset
select
    event_id
    ,datetime_id
    ,lookup_1
    ,lookup_2
    --,etc
from raw_event_data
where event_id >= @start_range --event_id *must* have an HG index on it for this to be worthwhile.
and event_id <= @end_range

--then run your normal query, except replace raw_event_data with raw_event_subset
select
    event_id
    ,datetime_id
    ,l1.lookup_desc
    ,l2.lookup_desc
    --etc
from raw_event_subset r
left join lookup_table l1
    on l1.lookup_id = r.lookup_1
left join lookup_table l2
    on l2.lookup_id = r.lookup_2
    --etc

drop table raw_event_subset

希望这可以帮助...

于 2013-08-02T04:52:33.853 回答
0

相关子查询可能是要走的路:

   SELECT r.event_id
        , r.datetime_id
        , (select lookup1.lookup_desc from lookup_table lookup1 where lookup1.lookup_id = r.lookup_1) as desc_1
        , (select lookup2.lookup_desc from lookup_table lookup2 where lookup2.lookup_id = r.lookup_2) as desc_2
        , (select lookup3.lookup_desc from lookup_table lookup3 where lookup3.lookup_id = r.lookup_3) as desc_3
        , (select lookup4.lookup_desc from lookup_table lookup4 where lookup4.lookup_id = r.lookup_4) as desc_4
     FROM Raw_Event_data r
    WHERE r.event_id = 1
        ;
于 2013-07-31T22:54:05.857 回答