情况:
我在一个实际网站上有一个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
答案 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 join
或select 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
条款中使用,但会在您的JOINS
和ORDER 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)
尝试创建INDEX cl_ordersummary_studentID ON cl_ordersummary(studentID)
其他索引也可以提供帮助,但您必须使用前缀搜索进行此优化,SQL数据库通常会将前缀搜索转换为索引范围扫描。例如,您可以索引电子邮件并使用prefix作为参数:
MySQL http://dev.mysql.com/doc/refman/5.0/en/fulltext-natural-language.html(所有主要数据库都有类似的搜索功能)