2011-05-05 46 views
2

我正在構建一個應用程序,該應用程序使用多個連接執行主查詢。這個查詢數據隨後可供整個應用程序在全局變量中使用。查詢刷新或獲取每個頁面刷新的最新結果集;所以它只是在請求的生命中處於相同的狀態。加快QoQ或其他方法?

在這個應用程序的其他部分,我有時會在這個數據上運行100個QoQ,通常是遞歸函數調用的結果。然而,儘管QoQ是一個很棒的功能,但速度並不是很快,而且在糟糕的一天中頁面加載時間可能在3000 - 5000毫秒之間。這只是不夠快。

是否有任何一種優化技術可以讓QoQ更快地執行或可能是另一種方法?我在Duplicate()函數中閱讀了Ben Nadel撰寫的一篇有趣的文章 - 是否有使用這個的範圍,如果有的話,怎麼做?

我很想聽聽你的想法。

不要擔心瘋狂的建議,這是一個個人項目,所以我願意承擔風險。我在軌道上運行與CF8兼容。

非常感謝, Michael。

+0

全局查詢在每個頁面視圖上都會更新?這不會導致衝突,在事先請求仍在運行的同時更新數據? – Yisroel 2011-05-05 15:46:55

+0

這個全局查詢中的所有QoQ都是簡單的選擇來檢索數據以供查看。此查詢沒有更新。 QoQ只是檢索並顯示最新的結果集,因此即使DB記錄有更新,也無關緊要。 – 2011-05-05 15:57:52

回答

2

沒有看到QoQ的代碼和複雜性,很難肯定地說最好的方法,但是你可以做的一件事就是使用一個結構來索引QoQ之外的記錄。使用QoQ的大部分開銷是構建新的查詢對象,並且使用結構只寫方法比循環遍歷原始查詢和比較更有效。

例如:

<!--- build up index ---> 
<cfset structindex = {} /> 
<cfset fields = "first,last,company" /> 
<cfloop list="#fields#" index="field"> 
    <cfset key = "field:#field#,value:#q[field][currentrow]#" /> 
    <!--- initialize each key (instead of using stuctkeyexists) ---> 
    <cfloop query="q"> 
     <cfset structindex[key] = "" /> 
    </cfloop> 
    <cfloop query="q"> 
     <!--- update each key with list of matching row indexes ---> 
     <cfset structindex[key] = listappend(structindex[key], currentrow) /> 
    </cfloop> 
</cfloop> 

<!--- save structindex to global variable ---> 

<!--- output rows matching index ---> 
<cfset key = "field:company,value:stackexchange" /> 
<cfoutput> 
    <cfloop list="#structindex[key]#" index="row"> 
     #q.last[row]#, #q.first[row]# (#q.company[row]#)<br /> 
    </cfloop> 
</cfoutput> 

如果這不符合您的需要提供環比語句的一些例子,多少條記錄在主查詢。

1

首先,我會看看主查詢所用的時間。如果它可以緩存一段時間,並佔用大量的頁面加載時間,我會緩存它。

接下來,我會看遞歸調用。如果他們可以迭代,那可能會加快速度。我意識到這並不總是可能的。如果這不是你最大的時間,我會很驚訝。儘管不知道更多關於你在做什麼,但很難幫助你優化它。

我也可以考慮在數據庫服務器上編寫一些遞歸的QoQs存儲過程,該服務器旨在快速處理數據並有效地切片和切片。 CF不是--QQ是非常有用的,但不是速度惡魔(正如你所指出的)。

最後,我會尋找straightfoward過濾器,而不是使用QoQ。相反,我只需在標準cfoutput標籤中的主查詢上運行一個循環,並即時進行過濾。這意味着您正在遍歷主查詢一次,而不是一次查詢主查詢,一次查詢結果查詢。

+0

主查詢很快,所以它不是一個問題。你是對的 - 遞歸調用時間最長。我基本上有一些我需要動態查找並獲取數據的孩子/父母關係。例如,如果我有10個項目並循環它們,則每個項目都可能調用一個函數,該函數進一步QoQ與其父項建立關係,等等直到它達到頂層。想象一下,這有點像CMS中的動態網站地圖結構。有更好的方法嗎?我可以寫一個函數來獲得一棵樹 - 但我需要在飛行中調用。 – 2011-05-05 16:14:56

+0

我可以想象幾件事情可以嘗試。拳頭,如果你可以避免一次推動每一個級別,你可能會創建一個可點擊的樹(或任何你的顯示結構),並進行AJAX調用以獲得下一級的按需。您也可以嘗試讓數據庫完成QoQ現在所做的工作,交換網絡開銷以便可能更快的查詢。您也可以嘗試通過將每個節點推入堆棧並逐個彈出它們來迭代地編寫這些代碼,但與前兩個建議相比,這需要更多時間進行編碼。 – 2011-05-06 13:27:37

1

這裏有兩個主要的解決方案。首先,你可以用CF之外的記錄做一些事情。我已經發布了我的建議。另一個是在db中完成所有的事情。我發現這樣做的一種方法是使用子查詢作爲臨時表。你甚至可以將sql語句保存在一個全局變量中,然後在你當前使用QoQ的相同位置引用它,但是對數據庫進行真正的查詢。這可能聽起來比一次去DB的旅程慢,然後很多QoQ,但實際上它可能不是有效索引。

select * 
from (
    #sqlstring# 
) as tmp 
where company = 'stackexchange' 

其實我已經與這兩個複雜的標準是什麼記錄用戶應該有機會獲得,然後同時他們可以過濾對這些記錄進行這一系統。採用這種方法意味着您始終知道內部記錄的來源,而不是試圖確保每個查詢都能正確拉取。

編輯: 在任何可能的情況下使用queryparams實際上更安全(通常更高效)。我發現這可以通過包含sql語句的文件來完成......

select * 
from (
    <cfinclude template="master_subquery.cfm" /> 
) as tmp 
where company = 'stackexchange'