这个coldfusion9 SQL搜索查询能否更快?

时间:2011-10-11 15:01:10

标签: mysql sql search coldfusion

情况:
我在一个实际网站上有一个6000名学生的数据库,在一个测试网站上,有一个由400名测试学生组成的数据库。使用搜索功能(下面)搜索学生在测试站点上工作正常,但在实际站点上搜索功能需要1-2分钟才能返回(甚至需要通过执行RequestTimeout = 180来增加脚本超时/ em>的)。两个站点都使用相同的搜索功能(如下)。

问题:
我的问题是,您是否有任何关于如何更快地进行此搜索的提示?这太慢了。

搜索功能:

<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

4 个答案:

答案 0 :(得分:2)

是否可以预期并希望每个学生在记录集中有多个联系人姓名?这个设置,您在订单表中有联系人姓名,而不是学生表,这看起来创建了一个不太理想的查询的必要性。我知道当然可能有充分的理由,但值得一试。那么,你想要/期待这个吗?

studentId|email|password|studentType|contactFirstName|contactLastName
999       b@b.b|p455w0rd|slacker    |billy           |bob
999       b@b.b|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和外键。

答案 1 :(得分:1)

  

这个coldfusion9 SQL搜索查询能否更快?

是。您想为受影响的列配置indexes

答案 2 :(得分:1)

Coldfusion不会执行您的查询。它被传递到您的数据库服务器以供执行,然后传回结果集。

您可以接受查询并使用查询分析器生成执行计划,以查看查询占用时间最多的位置。您很可能需要在WHERE条件中使用的列上添加一些索引。我相信MySQL,您可以使用EXPLAIN向您显示缺少索引的位置http://dev.mysql.com/doc/refman/5.5/en/using-explain.html

答案 3 :(得分:1)

  1. 尝试创建INDEX cl_ordersummary_studentID ON cl_ordersummary(studentID)

  2. 其他索引也可以提供帮助,但您必须使用前缀搜索进行此优化,SQL数据库通常会将前缀搜索转换为索引范围扫描。例如,您可以索引电子邮件并使用prefix作为参数:

    1. 全文搜索索引是优化的最佳选择,请参阅RDBMS功能的文档,大多数数据库支持通过特殊函数或语法对其进行全文搜索。您将在全文搜索中找到其他有用的功能,例如按最佳匹配排序。如果您更改查询以使用全文搜索,则不需要选项2。
    2. MySQL http://dev.mysql.com/doc/refman/5.0/en/fulltext-natural-language.html(所有主要数据库都有类似的搜索功能)