2013-03-28 142 views
0

我從表中的第一個查詢需要約40秒,創造超過80,000行。我想通過Site,Sequence,Total和任何操作系統版本獲得Windows 7應用程序的計數。優化性能

這些子查詢的工作,但他們當然大大延緩下跌過程。花了3.5小時跑步。

有沒有更有效的方法來做到這一點?

輸出:

SoftwareName Sequence Site Win7/site  Win7Installs/seq TotWin7apps TotalInstalls 
Adobe Acrobat  1  BKN   1     5    626   7854 
AutoCAD LT   1  BKN   1     1    3   15 
Adobe Acrobat  1  CTW   4     5    626   7854 
Adobe Captivate  1  CTW   1     1    8   60 

查詢:

WITH PCapps AS (
SELECT DISTINCT 
    Computer, 
    Sequence, 
    Site, 
    SoftwareName, 
    OS 
FROM table 
) 

SELECT DISTINCT 
    SoftwareName, 
    Sequence, 
    Site, 
    (SELECT COUNT(p1.SoftwareName) FROM PCapps p1 WHERE p1.SoftwareName = pc.Softwarename AND OS = 'Windows 7 Enterprise' AND p1.Site = pc.Site) as 'Win7/site', 
    (SELECT COUNT(p1.SoftwareName) FROM PCapps p1 WHERE p1.SoftwareName = pc.Softwarename AND OS = 'Windows 7 Enterprise' AND p1.Sequence = pc.Sequence) as 'Win7Installs/seq', 
    (SELECT COUNT(p2.SoftwareName) FROM PCapps p2 WHERE p2.SoftwareName = pc.Softwarename AND OS = 'Windows 7 Enterprise') as TotWin7apps, 
    (SELECT COUNT(p3.SoftwareName) FROM PCapps p3 WHERE p3.SoftwareName = pc.SoftwareName) as TotalInstalls 
    FROM PCapps pc 

**更新:

運用@Jason卡特的技巧,我創建了幾個#TEMP表,加入他們的行列。結果在不到一分鐘的時間內運行得非常快(不比初始查詢長很多)。此方法與@ JasonCarter的解決方案略有不同,因爲我按照他的初始技巧創建#temp表。我創建了幾個#temp表,每個表都包含COUNT()。

SELECT DISTINCT 
    Computer, 
    Sequence, 
    Site, 
    SoftwareName, 
    OS 
INTO #PCapps 
     FROM TABLE  

SELECT 
    SoftwareName, 
    Site, 
    COUNT(SoftwareName) AS [SiteInstalls] 
INTO #SiteInstalls 
FROM #PCapps 
    WHERE OS = 'Windows 7 Enterprise' 
    GROUP BY Site, SoftwareName 

SELECT 
    SoftwareName, 
    Sequence, 
    COUNT(SoftwareName) AS [SeqInstalls] 
INTO #SeqInstalls 
FROM #PCapps 
    WHERE OS = 'Windows 7 Enterprise' 
    GROUP BY Sequence, SoftwareName 

SELECT 
    SoftwareName, 
    COUNT(SoftwareName) AS [Win7Installs] 
INTO #Win7Installs 
FROM #PCapps 
    WHERE OS = 'Windows 7 Enterprise' 
    GROUP BY SoftwareName 

SELECT 
    SoftwareName, 
    COUNT(SoftwareName) AS [AppInstalls] 
INTO #AppInstalls 
FROM #PCapps 
    GROUP BY SoftwareName 

SELECT 
    pc.SoftwareName, 
    pc.Sequence, 
    pc.Site, 
    sit7.SiteInstalls, 
    seq7.SeqInstalls, 
    w7.Win7Installs, 
    ai.AppInstalls 
    FROM #PCapps pc 
    LEFT OUTER JOIN #SiteInstalls sit7 ON sit7.SoftwareName = pc.SoftwareName AND sit7.Site = pc.Site 
    LEFT OUTER JOIN #SeqInstalls seq7 ON seq7.SoftwareName = pc.SoftwareName AND seq7.Sequence = pc.Sequence 
    LEFT OUTER JOIN #Win7Installs w7 ON w7.SoftwareName = pc.SoftwareName 
    LEFT OUTER JOIN #AppInstalls ai ON ai.Softwarename = pc.SoftwareName 

DROP TABLE #PCapps 
DROP TABLE #SiteInstalls 
DROP TABLE #SeqInstalls 
DROP TABLE #Win7Installs 
DROP TABLE #AppInstalls 

回答

1

我會嘗試運行子查詢第一次進入臨時表來收集您的計數,然後拉總數。使用查詢設置的方式,每行PCapps都會運行一次這些子查詢,這就是爲什麼它需要這麼長時間。

嘗試這樣:

declare @t table (Computer varchar(10), Sequence int, Site varchar(3), SoftwareName varchar(20), OS varchar(20)) 

insert into @t values 
('C1',1,'BKN','Adobe Acrobat','Win7') 
,('C2',1,'BKN','Adobe Acrobat','Win7') 
,('C3',1,'BKN','Adobe Acrobat','Win7') 
,('C1',1,'BKN','AutoCAD LT ','Win7') 
,('C3',1,'BKN','AutoCAD LT ','Win7') 
,('B1',2,'CTW','Adobe Acrobat','Win7') 
,('B2',2,'CTW','Adobe Acrobat','Win7') 
,('B3',3,'CTW','Adobe LT','Win7') 
,('B4',3,'CTW','Adobe Acrobat','Win7') 
,('A1',2,'CTW','Adobe Acrobat','Win7') 
,('A2',2,'CTW','Adobe LT','Win7') 
,('A3',2,'CTW','Adobe Acrobat','Win7') 
,('X4',3,'CTW','Adobe Acrobat','WinXP') 
,('X1',2,'CTW','Adobe Acrobat','WinXP') 
,('X2',2,'CTW','Adobe LT','WinXP') 
,('X3',2,'CTW','Adobe Acrobat','WinXP') 
,('A4',2,'CTW','Adobe Acrobat','Win7'); 

SELECT 
    Site, 
    OS, 
    SoftwareName, 
    Sequence, 
    COUNT(SoftwareName) as 'Count' 
into #SiteSpecific 
FROM @t 
group by Site, OS, SoftwareName, Sequence; 


WITH PCapps AS (
SELECT DISTINCT 
    Computer, 
    Sequence, 
    Site, 
    SoftwareName, 
    OS 
FROM @t 
) 
SELECT 
    DISTINCT 
    PC.SoftwareName, 
    PC.Sequence, 
    PC.Site, 
    PerSeq.[Count] as 'Win7Installs/seq', 
    PerSite.[Count] as TotWin7apps, 
    total.[Count] as TotalInstalls 
FROM PCapps pc 
inner join (select SoftwareName, Sequence, OS, sum([Count]) [Count] from #SiteSpecific group by SoftwareName, Sequence, OS) PerSeq 
    on PerSeq.SoftwareName = pc.Softwarename 
    AND PerSeq.Sequence = pc.Sequence 
    AND PerSeq.OS = pc.OS 
inner join (select SoftwareName, Site, OS, sum([Count]) [Count] from #SiteSpecific group by SoftwareName, Site, OS) PerSite 
    on PerSite.SoftwareName = pc.Softwarename 
    AND PerSite.Site = pc.Site 
    AND PerSite.OS = pc.OS 
inner join (select SoftwareName, sum([Count]) [Count] from #SiteSpecific group by SoftwareName) Total 
    on Total.SoftwareName = pc.Softwarename 
where Pc.OS='Win7' 
order by SoftwareName, Sequence, Site 
+0

我包括我與我的問題的答案基於您最初的評論創建#temp表。它運行每個子查詢一次,然後將它們連接在一起以快速顯示結果。謝謝! – kevro

0

真的令我感到詫異......優化採用並行的優勢,使子查詢效率非常高。我填寫了一張有120K記錄的虛擬桌面,並嘗試了下面的內容。第三個查詢只比第一個(你的)查詢效率稍高,但代價是更復雜。我會離開你的。可能有更好的解決方案,但你對我看起來足夠好。你們需要多長時間來處理80K行?

WITH PCapps2 AS (
SELECT DISTINCT 
    Computer, 
    Sequence, 
    Site, 
    SoftwareName, 
    OS 
FROM pcapps 
) 
SELECT DISTINCT 
    SoftwareName, 
    Sequence, 
    Site, 
    (SELECT COUNT(p1.SoftwareName) FROM PCapps2 p1 WHERE p1.SoftwareName = pc.Softwarename AND OS = 'Windows 7 Enterprise' AND p1.Site = pc.Site) as 'Win7/site', 
    (SELECT COUNT(p1.SoftwareName) FROM PCapps2 p1 WHERE p1.SoftwareName = pc.Softwarename AND OS = 'Windows 7 Enterprise' AND p1.Sequence = pc.Sequence) as 'Win7Installs/seq', 
    (SELECT COUNT(p2.SoftwareName) FROM PCapps2 p2 WHERE p2.SoftwareName = pc.Softwarename AND OS = 'Windows 7 Enterprise') as TotWin7apps, 
    (SELECT COUNT(p3.SoftwareName) FROM PCapps2 p3 WHERE p3.SoftwareName = pc.SoftwareName) as TotalInstalls 
    FROM PCapps2 pc 

;WITH PCapps2 AS (
SELECT DISTINCT 
    Computer, 
    Sequence, 
    Site, 
    SoftwareName, 
    OS 
FROM pcapps 
) 
SELECT DISTINCT 
    SoftwareName, 
    Sequence, 
    Site, 
    COUNT(case when os = 'Windows 7 Enterprise' then 1 end) over (partition by pc.Softwarename,pc.Site) as 'Win7/site', 
    COUNT(case when os = 'Windows 7 Enterprise' then 1 end) over (partition by pc.Softwarename,pc.Sequence) as 'Win7Installs/seq', 
    COUNT(case when os = 'Windows 7 Enterprise' then 1 end) over (partition by pc.Softwarename) as TotWin7apps, 
    COUNT(*) over (partition by pc.Softwarename) as TotalInstalls 
    FROM PCapps2 pc 

;WITH PCapps2 AS (
SELECT DISTINCT 
    Computer, 
    Sequence, 
    Site, 
    SoftwareName, 
    OS 
FROM pcapps 
), a as (
    select softwarename, site, COUNT(*) as 'Win7/site' 
    from pcapps2 
    where os = 'Windows 7 Enterprise' 
    group by softwarename, site 
), b as (
    select softwarename, sequence, COUNT(*) as 'Win7Installs/seq' 
    from pcapps2 
    where os = 'Windows 7 Enterprise' 
    group by softwarename, sequence 
), c as (
    select softwarename, COUNT(case when os = 'Windows 7 Enterprise' then 1 end) as TotWin7apps, COUNT(*) as TotalInstalls 
    from pcapps2 
    group by softwarename 
), d as (
    select distinct softwarename, sequence, site 
    from pcapps2 
) 
select d.*, isnull(a.[Win7/site], 0) as [Win7/site], isnull(b.[Win7Installs/seq],0) as [Win7Installs/seq] 
     , isnull(c.TotWin7apps,0) as TotWin7apps, isnull(c.TotalInstalls, 0) as TotalInstalls 
from d 
     left join a on d.softwarename = a.softwarename and d.site = a.site 
     left join b on d.softwarename = b.softwarename and d.sequence = b.sequence 
     left join c on d.softwarename = c.softwarename 

第一個查詢: 表'pcapps'。掃描計數15,邏輯讀取6630,物理讀取0,預讀0,lob邏輯讀取0,lob物理讀取0次,lob預讀0 表「工作臺」。掃描計數0,邏輯讀取0,物理讀取0,預讀讀取0,lob邏輯讀取0,lob物理讀取0,lob預讀取讀取0.

第二查詢: 表'pcapps'。掃描計數3,邏輯讀取1326,物理讀取0,預讀0,lob邏輯讀取0,lob物理讀取0次,lob預讀0 表「工作臺」。掃描計數18,邏輯讀取1983591,物理讀取0,預讀讀取0,lob邏輯讀取0,lob物理讀取0,lob預讀取讀取0.

第三查詢: 表'pcapps'。掃描計數12,邏輯讀取5304,物理讀取0,預讀0,lob邏輯讀取0,lob物理讀取0次,lob預讀0 表「工作臺」。掃描計數0,邏輯讀取0次,物理讀取0次,預讀0,lob邏輯讀取0,lob物理讀取0次,lob預讀0

+0

來自幾個連接表的初始查詢在38秒內選擇80,000條記錄。帶有子查詢的完整查詢在昨天運行,耗時3.5小時。使用@JasonCarter的提示,查詢在一分鐘內運行。 – kevro