【发布时间】:2015-10-26 16:43:26
【问题描述】:
我已经在网站上查看了有关此问题的相关问题,但没有一个真正回答我的问题。我在使用 Propel 的网站中有以下语句:
$query = $query
->distinct()
->select(Request::getTransferFieldsWithRelations())
->leftJoinResponse("Response")
->joinWith("Request.SupportStatus SupportStatus")
->joinWith("Request.CustomerGroup CustomerGroup", Criteria::LEFT_JOIN)
->joinWith("Request.Customer Customer", Criteria::LEFT_JOIN)
->joinWith("Request.Site Site", Criteria::LEFT_JOIN)
->joinWith("Request.InternalUser InternalUser", Criteria::LEFT_JOIN)
->joinWith("Request.User User", Criteria::LEFT_JOIN)
->orderBy("CreatedDate", Criteria::ASC);
$conditions = array(
"and" => array(),
"or" => array()
);
if(isset($args["QueryText"]) && $args["QueryText"] != "") {
$query = $query
->withColumn("(MATCH (Request.Subject, Request.Detail) AGAINST ('" . $args["QueryText"] . "' IN BOOLEAN MODE) + MATCH (Response.Response) AGAINST ('" . $args["QueryText"] . "' IN BOOLEAN MODE))", "RequestRelevance")
->condition('cond1', "(MATCH (Request.Subject, Request.Detail) AGAINST ('" . $args["QueryText"] . "' IN BOOLEAN MODE) + MATCH (Response.Response) AGAINST ('" . $args["QueryText"] . "' IN BOOLEAN MODE)) > 0.2")
->condition('cond2', 'Request.Id = ?', $args["QueryText"])
->where(array('cond1', 'cond2'), 'or')
->orderBy("RequestRelevance", Criteria::DESC);
}
if(isset($args["OpenCallsOnly"]) && $args["OpenCallsOnly"] == 1) {
$query = $query
->useSupportStatusQuery()
->filterByOutstanding(1)
->endUse();
}
if(isset($args["ClosedCallsOnly"]) && $args["ClosedCallsOnly"] == 1) {
$query = $query
->useSupportStatusQuery()
->filterByIsClosed(1)
->endUse();
}
...
foreach ($conditions as $key => $value) {
if(!empty($value)){
$query = $query
->where($value, $key);
}
}
但是,如果按ClosedCallsOnly 排序(接近 50000 个结果),则此查询在网站上执行需要 20 秒,如果使用原始 SQL,则需要超过 8 秒。我已使用UNION 语句将其优化为以下查询:
(SELECT DISTINCT
requests.requestID AS "Id", requests.subject AS "Subject", requests.detail AS "Detail", requests.created AS "CreatedDate", requests.lastresponsedate AS "LastResponseDate", SupportStatus.supportstatusID AS "SupportStatus.Id", SupportStatus.supportstatus AS "SupportStatus.Name", SupportStatus.isnew AS "SupportStatus.IsNew", SupportStatus.isclosed AS "SupportStatus.IsClosed", CustomerGroup.customergroupID AS "CustomerGroup.Id", CustomerGroup.customergroup AS "CustomerGroup.Name", Site.siteID AS "Site.Id", Site.site AS "Site.Name", InternalUser.userID AS "InternalUser.Id", InternalUser.username AS "InternalUser.Username", User.userID AS "User.Id", User.username AS "User.Username", Customer.customerID AS "Customer.Id", Customer.customer AS "Customer.Name", Customer.customergroupID AS "Customer.CustomerGroupId", Customer.rate AS "Customer.Rate"
FROM requests
LEFT JOIN responses Response ON (requests.requestID=Response.requestID)
INNER JOIN supportstatus SupportStatus ON (requests.supportstatusID=SupportStatus.supportstatusID)
INNER JOIN customergroups CustomerGroup ON (requests.customergroupID=CustomerGroup.customergroupID)
INNER JOIN customers Customer ON (requests.customerID=Customer.customerID)
INNER JOIN sites Site ON (requests.siteID=Site.siteID)
LEFT JOIN users InternalUser ON (requests.internal_userID=InternalUser.userID)
LEFT JOIN users User ON (requests.userID=User.userID)
WHERE ((MATCH (requests.subject, requests.detail) AGAINST ('slow pc' IN BOOLEAN MODE)
))
ORDER BY requests.created ASC)
UNION
(SELECT DISTINCT
requests.requestID AS "Id", requests.subject AS "Subject", requests.detail AS "Detail", requests.created AS "CreatedDate", requests.lastresponsedate AS "LastResponseDate", SupportStatus.supportstatusID AS "SupportStatus.Id", SupportStatus.supportstatus AS "SupportStatus.Name", SupportStatus.isnew AS "SupportStatus.IsNew", SupportStatus.isclosed AS "SupportStatus.IsClosed", CustomerGroup.customergroupID AS "CustomerGroup.Id", CustomerGroup.customergroup AS "CustomerGroup.Name", Site.siteID AS "Site.Id", Site.site AS "Site.Name", InternalUser.userID AS "InternalUser.Id", InternalUser.username AS "InternalUser.Username", User.userID AS "User.Id", User.username AS "User.Username", Customer.customerID AS "Customer.Id", Customer.customer AS "Customer.Name", Customer.customergroupID AS "Customer.CustomerGroupId", Customer.rate AS "Customer.Rate"
FROM requests
LEFT JOIN responses Response ON (requests.requestID=Response.requestID)
INNER JOIN supportstatus SupportStatus ON (requests.supportstatusID=SupportStatus.supportstatusID)
INNER JOIN customergroups CustomerGroup ON (requests.customergroupID=CustomerGroup.customergroupID)
INNER JOIN customers Customer ON (requests.customerID=Customer.customerID)
INNER JOIN sites Site ON (requests.siteID=Site.siteID)
LEFT JOIN users InternalUser ON (requests.internal_userID=InternalUser.userID)
LEFT JOIN users User ON (requests.userID=User.userID)
WHERE (requests.requestID = 'slow pc')
ORDER BY requests.created ASC)
UNION
(SELECT DISTINCT
Request.requestID AS "Id", Request.subject AS "Subject", Request.detail AS "Detail", Request.created AS "CreatedDate", Request.lastresponsedate AS "LastResponseDate", SupportStatus.supportstatusID AS "SupportStatus.Id", SupportStatus.supportstatus AS "SupportStatus.Name", SupportStatus.isnew AS "SupportStatus.IsNew", SupportStatus.isclosed AS "SupportStatus.IsClosed", CustomerGroup.customergroupID AS "CustomerGroup.Id", CustomerGroup.customergroup AS "CustomerGroup.Name", Site.siteID AS "Site.Id", Site.site AS "Site.Name", InternalUser.userID AS "InternalUser.Id", InternalUser.username AS "InternalUser.Username", User.userID AS "User.Id", User.username AS "User.Username", Customer.customerID AS "Customer.Id", Customer.customer AS "Customer.Name", Customer.customergroupID AS "Customer.CustomerGroupId", Customer.rate AS "Customer.Rate"
FROM responses
LEFT JOIN requests Request ON (Request.requestID=responses.requestID)
INNER JOIN supportstatus SupportStatus ON (Request.supportstatusID=SupportStatus.supportstatusID)
INNER JOIN customergroups CustomerGroup ON (Request.customergroupID=CustomerGroup.customergroupID)
INNER JOIN customers Customer ON (Request.customerID=Customer.customerID)
INNER JOIN sites Site ON (Request.siteID=Site.siteID)
LEFT JOIN users InternalUser ON (Request.internal_userID=InternalUser.userID)
LEFT JOIN users User ON (Request.userID=User.userID)
WHERE ((
MATCH (responses.response) AGAINST ('slow pc' IN BOOLEAN MODE)))
ORDER BY Request.created ASC)
该语句的执行时间大约提高了 8 倍,这确实很好,但不幸的是,我不确定如何将其转换为 Propel 查询。从查看其他问题来看,似乎在 Propel 中使用 UNION 是不可能的。我知道在 Propel 中使用 SQL 语句是可能的,但是由于 Propel 查询在这个类的其他地方都被使用,我不确定这怎么可能?我怎样才能在我的网站中实现这个查询?如果需要,我可以为这个类提供更多代码。
【问题讨论】:
-
有时您只需要编写原始 SQL,尤其是在优化此类大型查询时。