简体   繁体   English

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

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

The Situation: 情况:
I have a database of 6000 students on a live site, and on a test site, there is a database of 400 test-students. 我在一个现场站点上有6000名学生的数据库,而在一个测试站点上,有400名测试学生的数据库。 Searching the students using the search function (below) works fine on the test site, but on the live site the search function takes 1-2 full minutes to return ( Even needed to increase the script timeout by doing RequestTimeout=180 ). 使用搜索功能(如下)搜索学生在测试站点上可以正常工作,但是在实时站点上,搜索功能需要1-2整分钟才能返回( 甚至需要通过执行RequestTimeout = 180来增加脚本超时 )。 Both sites use the same search function (below). 两个站点使用相同的搜索功能(如下)。

The Question: 问题:
My question is do any of you have any tips on how to make this search any faster? 我的问题是,您有没有关于如何更快地进行搜索的提示? It's just so slow. 太慢了

The Search Function: 搜索功能:

<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 Descriptions: 表说明:
( Simple representations of each table used in search ) 用于搜索的每个表的简单表示

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

Is it expected and wanted that you'll have multiple contact names in the recordset for each student? 是否期望并希望您在每个学生的记录集中有多个联系人姓名? That setup, where you have contact names in the order table, as opposed to the student table looks to be creating the necessity for a query that is less than optimal. 这种设置(在订单表中有联系人姓名而不是学生表)在这种情况下似乎正在创建查询的必要性,而不是最优的。 I understand that there may be good reason for that, of course, but worth checking. 我了解,当然有充分的理由,但值得检查。 So, do you want/expect this? 那么,您是否想要/期望这个?

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

If so, not sure how the second query could be any faster. 如果是这样,则不确定第二个查询如何更快。 However, the first query might benefit from changing to the following that will always only return a single row and not require a left join or a select distinct : 但是,第一个查询可能会受益于更改为以下查询,该查询将始终仅返回单行,而无需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#%"> )
)             

Another thing to look at is indexes. 另一件事要看的是索引。 The indexes won't be used in your LIKE clauses, but will be on your JOINS and your ORDER BY clause. 索引不会在您的LIKE子句中使用,但会在您的JOINSORDER BY子句中使用。 Make sure you have appropriate indexes on the tables and that your Pimary and Foreign Keys are defined. 确保在表上有适当的索引,并且已定义了“ Pimary”和“ Foreign Key”。

Can this coldfusion9 SQL search query be made faster? 可以使ColdFold9 SQL搜索查询更快吗?

Yes. 是。 You want to configure indexes for affected columns. 您要为受影响的列配置索引

Coldfusion does not execute your query. Coldfusion不执行您的查询。 It's passed to your database server for execution and the result set is then passed back. 它被传递到您的数据库服务器以执行,然后将结果集传递回去。

You can take your query and use a query analyzer to generate an execution plan to see where your query is taking the most time. 您可以查询并使用查询分析器来生成执行计划,以查看查询花费最多的时间。 You most likely need to add some indexes on the columns being used in your WHERE criteria. 您很可能需要在WHERE条件中使用的列上添加一些索引。 I believe in MySQL you can use EXPLAIN to show you where indexes are missing http://dev.mysql.com/doc/refman/5.5/en/using-explain.html 我相信在MySQL中,您可以使用EXPLAIN向您显示缺少索引的位置http://dev.mysql.com/doc/refman/5.5/en/using-explain.html

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

  2. Other indexes can help too but you have to to use prefix search for this optimization, SQL databases usually convert prefix search to index range scan. 其他索引也可以提供帮助,但是您必须使用前缀搜索进行此优化,SQL数据库通常将前缀搜索转换为索引范围扫描。 For example you can index email and use prefix as parameter : 例如,您可以索引电子邮件并将前缀用作参数:

  1. Full text search index is the best option to optimize, see docs for your RDBMS capabilities, most databases support full text search it via special functions or syntax. 全文搜索索引是优化的最佳选择,有关RDBMS功能的信息,请参阅文档。大多数数据库都通过特殊功能或语法支持全文搜索。 You will find other useful features in full text search for example to sort by best match. 您会在全文搜索中找到其他有用的功能,例如按最佳匹配进行排序。 You won't need option 2 if you change your queries to use full text search. 如果将查询更改为使用全文本搜索,则不需要选项2。

MySQL http://dev.mysql.com/doc/refman/5.0/en/fulltext-natural-language.html (All major databases have similar search capabilities ) 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