繁体   English   中英

可以使ColdFold9 SQL搜索查询更快吗?

[英]Can this coldfusion9 SQL search query be made faster?

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

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

搜索功能:

<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

是否期望并希望您在每个学生的记录集中有多个联系人姓名? 这种设置(在订单表中有联系人姓名而不是学生表)在这种情况下似乎正在创建查询的必要性,而不是最优的。 我了解,当然有充分的理由,但值得检查。 那么,您是否想要/期望这个?

studentId|email|password|studentType|contactFirstName|contactLastName
999       b@b.b|p455w0rd|slacker    |billy           |bob
999       b@b.b|p455w0rd|slacker    |bill            |bob
...

如果是这样,则不确定第二个查询如何更快。 但是,第一个查询可能会受益于更改为以下查询,该查询将始终仅返回单行,而无需left joinselect distinctselect 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”。

可以使ColdFold9 SQL搜索查询更快吗?

是。 您要为受影响的列配置索引

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

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

  1. 尝试在cl_ordersummary(studentID)上创建CREATE INDEX cl_ordersummary_studentID

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

  1. 全文搜索索引是优化的最佳选择,有关RDBMS功能的信息,请参阅文档。大多数数据库都通过特殊功能或语法支持全文搜索。 您会在全文搜索中找到其他有用的功能,例如按最佳匹配进行排序。 如果将查询更改为使用全文本搜索,则不需要选项2。

MySQL http://dev.mysql.com/doc/refman/5.0/en/fulltext-natural-language.html (所有主要数据库都具有类似的搜索功能)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM