現在、600 万行以上 (1 か月あたり約 60 万から 70 万行) を含む Transactions というテーブルがあります。
pk id acct_id id1 id2 id3 id4 created interface_id source_lvl1 source_lvl2 trans_type
------------------------------------------------------------ ----------- ----------- ----------- ----------- ----------- ----------- ----------------------- ------------ ----------- ----------- -----------
10000257.4297...400245990.3.1002 10000257 4297 NULL NULL NULL NULL 2012-09-06 11:26:30.000 1 32002 1002 3
10004819.1529.106.105442.400667675.6.1021 10004819 1529 106 105442 62 NULL 2012-09-11 08:34:35.000 4 32002 1021 6
10004819.1529.18664647.62.400667675.3.1021 10004819 1529 18664647 62 NULL NULL 2012-09-11 08:34:35.000 4 32002 1021 3
10006460.1529.106.105442.400667675.6.1021 10006460 1529 106 105442 62 NULL 2012-09-11 08:34:35.000 4 32002 1021 6
10006460.1529.18664647.62.400667675.3.1021 10006460 1529 18664647 62 NULL NULL 2012-09-11 08:34:35.000 4 32002 1021 3
10006648.3280...406204785.3.1002 10006648 3280 NULL NULL NULL NULL 2012-11-14 10:39:45.000 6 32002 1002 3
10006834.1529.106.105442.400667675.6.1021 10006834 1529 106 105442 62 NULL 2012-09-11 08:34:35.000 4 32002 1021 6
10006834.1529.18664647.62.400667675.3.1021 10006834 1529 18664647 62 NULL NULL 2012-09-11 08:34:35.000 4 32002 1021 3
10006962.2428...415795811.3.1018 10006962 2428 NULL NULL NULL NULL 2013-03-05 10:50:11.000 1 32002 1018 3
10006962.2428.107972..415795811.4.1018 10006962 2428 107972 NULL NULL NULL 2013-03-05 10:50:11.000 1 32002 1018 4
特定のイベントのカウントを容易にするビューを定義しました。
ここにSQL定義があります:
CREATE VIEW [dbo].[Queue_base]
AS
select
dateadd(minute , (DATEPART(minute,t.created)/30)*30 , DATEADD(hour,datediff(hour, 0, t.created), 0)) INTRVL_UTC,
dateadd(minute , (DATEPART(minute,t.created)/30)*30 + 30 , DATEADD(hour,datediff(hour, 0, t.created), 0)) INTRVL_END_UTC,
a.ID [Agent ID], a.Login, a.DisplayName, a.GroupName, q.QueueID, q.QueueName,
TODATETIMEOFFSET(t.created,0) created
,i.ReferenceNumber, t.id inc_id
, case when (t.trans_type=17 and t.source_lvl2 not IN (1001, 2001)) or (t.trans_type=6 and t.id1=8) then t.id else null end [Workload]
, case when (t.trans_type=6 and t.id1=8 and t.source_lvl2 not IN (1001, 2001) or (t.trans_type=17 and not t.source_lvl2 IN (1001,2001)))then t.id else null end [Inbound Emails]
, case when t.trans_type=17 and t.id1=q.QueueID then t.id else null end [EnQueued]
, case when t.trans_type=17 and t.id2=q.QueueID then t.id else null end [DeQueued]
, case when t.trans_type=6 and t.id1 IN (2,106) then t.id else null end [Solved]
, case when t.trans_type=6 and t.id1 =8 then t.id else null end [Updated]
, case when x.StatusTypeID = 2 then t.id else null end [Reopened]
, case when t.trans_type=6 and t.id1=125 then t.id else null end [Spam]
, case when t.trans_type=8 and t.acct_id <> 1 then t.id else null end [Responded]
, case when i.cr_rec_element_1 is not null or i.de_reason1 is not null then t.id else null end [Complaint]
,t.trans_type, t.id1
,r.Brand, r.Region, r.[Call Center], r.LOB, r.[LOB Detail], r.Team, r.Subteam, r.Channel
,r.Interface, r.Product, r.[Product Detail], r.Unit
from Transactions t
left join
(
select a.*, b.id1, st.StatusTypeID
from
(select
t1.pk, t1.id, t1.created, max(t2.created) maxdate
from Transactions t1
left join Transactions t2
on t1.id=t2.id and t2.created<t1.created and t2.trans_type=6
left join Status st on t2.id1=st.StatusID
where t1.trans_type=6 and t1.id1=8
group by t1.pk, t1.id, t1.created) a left join Transactions b on a.id=b.id and b.created=a.maxdate and b.trans_type=6
left join Status st on b.id1=st.statusid
)
x on t.pk=x.pk
left join Incident i on t.id=i.id
left join Account a on t.acct_id=a.ID
left join Queue q ON (t.trans_type=17 and (t.id1=q.QueueID or t.id2=q.QueueID) or t.trans_type IN (6,8) and t.id3=q.QueueID)
left join queuedim r ON (q.QueueName=r.QueueName or q.QueueName is null and r.QueueName is null)
and (q.QueueID=r.QueueID or q.QueueID is null and r.QueueID is null)
where t.trans_type=17 or t.trans_type IN (6,8)
これがビューの重要な部分です。
inc_id Workload Inbound Emails EnQueued DeQueued Solved Updated Reopened Spam Responded Complaint
----------- ----------- -------------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
10209648 NULL NULL NULL NULL 10209648 NULL NULL NULL NULL NULL
10209648 NULL NULL NULL NULL NULL NULL NULL NULL 10209648 NULL
10209648 10209648 NULL NULL NULL NULL 10209648 NULL NULL NULL NULL
10227966 NULL NULL NULL NULL NULL NULL NULL 10227966 NULL NULL
10288343 NULL NULL NULL NULL 10288343 NULL NULL NULL NULL NULL
10303898 NULL NULL NULL NULL 10303898 NULL NULL NULL NULL NULL
10394204 NULL NULL NULL NULL NULL NULL NULL 10394204 NULL NULL
10409624 NULL NULL NULL NULL 10409624 NULL NULL NULL NULL NULL
10482071 NULL NULL NULL NULL NULL NULL NULL 10482071 NULL NULL
10485993 NULL NULL NULL NULL NULL NULL NULL 10485993 NULL NULL
私の計画は、別のテーブルを作成し、興味のある集計結果でそれを更新し、期間と他のディメンションの組み合わせでグループ化することでした。問題は、上に示したイベントの個別のカウントと単純なカウントの両方が必要ですが、後者のビューでは生の結果がかなり速く生成されますが、カウントを含む別のクエリには時間がかかります。
-- month account
declare @d1 date
declare @d2 date
set @d1 = '2013-05-01'
set @d2 = '2013-06-01'
--insert into IncPerfQueue
select x.Brand, x.Region, x.[Call Center], x.LOB, x.[LOB Detail], x.Team, x.Subteam,
x.QueueName, case when x.[Agent ID] is null then 0 else [Agent ID] end, c.[month], NULL weekstart, NULL [date]
, count(distinct EnQueued) [Distinct Incidents EnQueued]
, count(distinct DeQueued) [Distinct Incidents DeQueued]
, count(distinct Solved) [Distinct Incidents Solved in the queue]
, COUNT(distinct Responded) [Distinct Incidents Responded in the queue]
, COUNT(distinct Updated) [Distinct Incidents Updated in the queue]
, count(distinct Reopened) [Distinct Incidents ReOpened in the queue]
, count(distinct Spam) [Distinct Spam closed in the queue]
, COUNT([Inbound Emails]) [Inbound Emails]
, COUNT(Workload) [Workload]
, count(EnQueued) [# EnQueued]
, count(DeQueued) [# DeQueued]
, count(Solved) [# Solved in the queue]
, COUNT(Responded) [# Responded in the queue]
, COUNT(Updated) [#Updated in the queue]
, count(Reopened) [# ReOpened in the queue]
, count(Spam) [# Spam closed in the queue]
from Queue_base x
join [calendar] c ON convert(date,x.created)=c.date
where x.created >= @d1 and x.created < @d2
and Brand is not null
group by x.Brand, x.Region, x.[Call Center], x.LOB, x.[LOB Detail], x.Team, x.Subteam,
x.QueueName, [Agent ID], c.month
これは必要なクエリの 1 つにすぎません。さまざまなディメンションの個別の集計が必要であり (グループごとの個別のカウント)、1 時間以上かかりました。 http://i.stack.imgur.com/oWibJ.png
この種のクエリに最適なアプローチについて、ご提案をいただければ幸いです。ベーステーブルはすぐに大きくなります...パーティション分割する必要がありますか? また、ここで参照されているすべてのテーブルにはインデックスが付けられており、私が使用していることにも注意してください。Microsoft SQL Server 2008 R2 (SP2)(X64) は、2x X5550 プロセッサと 48GB RAM を搭載したボックスにインストールされ、OS は Windows Server 2008 R2 Enterprise です。
ありがとう、マジュ