2011-10-11 39 views
0

現狀:
我有6000名學生上線的站點數據庫,並在試驗現場,有400測試學生的數據庫。使用搜索功能搜索學生(下圖)在測試網站上工作正常,但在現場網站上搜索功能需要1-2分鐘的時間才能返回(甚至需要通過執行RequestTimeout = 180來增加腳本超時)。這兩個網站使用相同的搜索功能(如下)。這個coldfusion9 SQL搜索查詢可以更快嗎?

問題:
我的問題是做任何你有關於如何使搜索更快了什麼祕訣?它太慢了。

搜索功能:

<cffunction name="getStudentsByKeyword" access="public" output="no" returntype="struct"> 
    <cfargument name="keyword" type="string" required="yes"> 
    <cfargument name="pageNum" type="numeric" default="1"> 
    <cfargument name="startIndex" type="numeric" default="1"> 
    <cfargument name="numItemsPerPage" type="numeric" default="20"> 

    <cfset var resultStruct = StructNew()> 
    <cfset resultStruct.numAllItems=0> 
    <cfset resultStruct.numDisplayedItems=0> 
    <cfset resultStruct.courses=QueryNew("studentID")> 

    <cfif Arguments.pageNum GT 1> 
     <cfset Arguments.startIndex=(Arguments.pageNum - 1) * Arguments.numItemsPerPage + 1> 
    </cfif> 

    <cfquery name="qNumStudents" datasource="#this.datasource#"> 
     SELECT DISTINCT COUNT(cl_student.studentID) AS numItems 
     FROM cl_student LEFT JOIN cl_ordersummary ON cl_student.studentID=cl_ordersummary.studentID 
     WHERE cl_student.email LIKE <cfqueryparam cfsqltype="cf_sql_char" value="%#Arguments.keyword#%"> OR 
      cl_ordersummary.contactFirstName LIKE <cfqueryparam cfsqltype="cf_sql_char" value="%#Arguments.keyword#%"> OR 
      cl_ordersummary.contactLastName LIKE <cfqueryparam cfsqltype="cf_sql_char" value="%#Arguments.keyword#%"> 
    </cfquery> 
    <cfset resultStruct.numAllItems = qNumStudents.numItems> 

    <cfquery name="qStudents" datasource="#this.datasource#"> 
     SELECT DISTINCT cl_student.studentID, cl_student.email, cl_student.password, cl_student.studentType, 
      cl_ordersummary.contactFirstName, cl_ordersummary.contactLastName 
     FROM cl_student LEFT JOIN cl_ordersummary ON cl_student.studentID=cl_ordersummary.studentID 
     WHERE cl_student.email LIKE <cfqueryparam cfsqltype="cf_sql_char" value="%#Arguments.keyword#%"> OR 
      cl_ordersummary.contactFirstName LIKE <cfqueryparam cfsqltype="cf_sql_char" value="%#Arguments.keyword#%"> OR 
      cl_ordersummary.contactLastName LIKE <cfqueryparam cfsqltype="cf_sql_char" value="%#Arguments.keyword#%"> 
     ORDER BY cl_student.email, cl_ordersummary.contactFirstName, cl_ordersummary.contactLastName 
     LIMIT #Arguments.startIndex-1#, #Arguments.numItemsPerPage# 
    </cfquery> 

    <cfset resultStruct.numDisplayedItems=qStudents.recordcount>  
    <cfset resultStruct.students = qStudents> 

    <cfreturn resultStruct> 
    </cffunction> 

表說明:

Table cl_student 
================ 
studentID, email, password, studentType, sendReminderEmail, firstName, middleName, lastName, address, city, state, zip, daytimePhone, dateCreated, dateLastModified 
---------------- 
studentID INT UNSIGNED(10) (PRIMARY) (AI) 
email VARCHAR(100) 
password VARCHAR(20) 
studentType ENUM('A','B','C','D','F') 
sendRemiderEmail TINYINT(4) 
firstName VARCHAR(30) 
middleName VARCHAR(30) 
lastName VARCHAR(30) 
address VARCHAR(100) 
city VARCHAR(30) 
state VARCHAR(30) 
zip VARCHAR(10) 
daytimePhone VARCHAR(20) 
dateCreated DATETIME 
dateLastModified DATETIME 


Table cl_ordersummary 
===================== 
orderID, studentID, orderDate, status, donationAmount, total, contactFirstName, contactLastName, contactAddress1, contactAddress2, contactCity, contactState, contactZIP, daytimePhone, cellPhone, billingFirstName, billingLastName, billingAddress1, billingAddress2, billingCity, billingState, billingZIP, payWithCash, authCode, remark, dateLastModified 
--------------------- 
orderID VARCHAR(20) (PRIMARY) 
studentID INT(11) 
orderDate DATETIME 
status CHAR(1) 
donationAmount FLOAT 
total FLOAT 
contactFirstName VARCHAR(50) 
contactLastName VARCHAR(50) 
contactAddress1 VARCHAR(100) 
contactAddress2 VARCHAR(100) 
contactCity VARCHAR(50) 
contactState VARCHAR(50) 
contactZIP VARCHAR(10) 
daytimePhone VARCHAR(30) 
cellPhone VARCHAR(30) 
billingFirstName VARCHAR(50) 
billingLastName VARCHAR(50) 
billingAddress1 VARCHAR(100) 
billingAddress2 VARCHAR(100) 
billingCity VARCHAR(50) 
billingState VARCHAR(50) 
billingZIP VARCHAR(10) 
payWithCash TINYINT(4) 
authCode VARCHAR(20) 
remark TEXT 
dateLastModified DATETIME 
+0

'DISTINCT'和'LIKE'是兩個可以執行較慢的操作。你的查詢計劃是什麼樣的?任何索引?另外,返回第一個查詢中的所有列,僅僅是爲了獲得行計數效率低下。你可以考慮使用'SQL_CALC_FOUND_ROWS' /'FOUND_ROWS()'來估計找到的總行數。至少,嘗試將第一個查詢轉換爲某種「COUNT(..)」http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows – Leigh

+0

確實(重新這兩個查詢)。就目前而言,您可能只需在ColdFusion中運行一個查詢和分頁即可 - 儘管只運行count()可能更可取。 –

回答

2

是否期望並希望您在每個學生的記錄集中都有多個聯繫人姓名?該設置(在訂單表中有聯繫人姓名)與學生表相對,這看起來是創建了一個不太理想的查詢的必要性。我明白,當然可能有很好的理由,但值得檢查。那麼,你想要嗎?

studentId|email|password|studentType|contactFirstName|contactLastName 
999  [email protected]|p455w0rd|slacker |billy   |bob 
999  [email protected]|p455w0rd|slacker |bill   |bob 
... 

如果是這樣,不知道第二個查詢如何更快。然而,第一個查詢可能會受益於改變到永遠只返回一個排,而不是需要一個left joinselect distinct如下:

SELECT count(s.*) as nAllResults 
FROM  cl_student s 
WHERE  s.email LIKE <cfqueryparam cfsqltype="cf_sql_char" value="%#Arguments.keyword#%"> 
OR EXISTS (
     SELECT 1 
     FROM cl_ordersummary o 
     WHERE o.studentId = s.studentId 
     AND (o.contactFirstName LIKE <cfqueryparam cfsqltype="cf_sql_char" value="%#Arguments.keyword#%"> 
     OR  o.contactLastName LIKE <cfqueryparam cfsqltype="cf_sql_char" value="%#Arguments.keyword#%">) 
)    

另一件事看的指標。您的LIKE條款中不會使用索引,但會在您的JOINSORDER BY條款中使用。確保你在表格上有適當的索引,並且你的Pimary和Foreign Key是被定義的。

+0

..並且在附註中,由於您的WHERE子句,您實際上正在執行「INNER JOIN」,而不是「LEFT JOIN」。 – Leigh

+0

大開眼界!謝謝。 – m0rtimer

1

可這coldfus(在搜索使用的每個表的簡單陳述) ion9 SQL搜索查詢速度會更快嗎?

是的。您想要爲受影響的列配置indexes

1

Coldfusion不會執行您的查詢。它傳遞給數據庫服務器執行,然後結果集被傳回。

您可以帶上您的查詢並使用查詢分析器生成執行計劃,以查看您的查詢花費的最多時間。您很可能需要在您的WHERE條件中使用的列上添加一些索引。我相信,在MySQL中,你可以使用EXPLAIN來顯示您在哪裏指標缺少http://dev.mysql.com/doc/refman/5.5/en/using-explain.html

1
  1. 嘗試CREATE INDEX cl_ordersummary_studentID ON cl_ordersummary(studentID)

  2. 其他指標也可以幫助你,但你必須使用前綴搜索對於這種優化,SQL數據庫通常將前綴搜索轉換爲索引範圍掃描。例如,你可以索引電子郵件和使用前綴作爲參數:

  1. 全文搜索索引是優化,看文檔爲您的RDBMS功能的最佳選擇,大多數的數據庫支持全文搜索它通過特殊的函數或語法。您可以在全文搜索中找到其他有用的功能,例如按最佳匹配進行排序。如果您更改查詢以使用全文搜索,則不需要選項2。

的MySQL http://dev.mysql.com/doc/refman/5.0/en/fulltext-natural-language.html(所有主要的數據庫有類似的搜索功能)