2015-10-21 13 views
6

Tôi làm việc trên một trang web chạy trên Propel ORM và tôi có truy vấn này:MySQL trận đấu ... Chống lại truy vấn rất chậm

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); 
} 

có thể dịch như sau trong SQL:

SELECT DISTINCT 
(MATCH (requests.subject, requests.detail) AGAINST ('46104' IN BOOLEAN MODE) + 
    MATCH (Response.response) AGAINST ('46104' IN BOOLEAN MODE)) 
    AS RequestRelevance, 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.twistedfish_userID=InternalUser.userID) 
    LEFT JOIN users User ON (requests.userID=User.userID) 
WHERE ((MATCH (requests.subject, requests.detail) AGAINST ('46104' IN BOOLEAN MODE) + 
    MATCH (Response.response) AGAINST ('46104' IN BOOLEAN MODE)) > 0.2 OR requests.requestID = '46104') 
ORDER BY requests.created ASC,RequestRelevance DESC 

Nó mất 20 giây để tải trên trang web bằng cách sử dụng Propel và 7.020 giây khi chạy truy vấn SQL.

tôi đã cố gắng một sau thay vì:

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.twistedfish_userID=InternalUser.userID) 
    LEFT JOIN users User ON (requests.userID=User.userID) 
WHERE (requests.subject LIKE '%46104%' OR requests.detail LIKE '%46104%' OR Response.response LIKE '%46104%' OR requests.requestID = '46104') 
ORDER BY requests.created 

mà mất 3,308 giây để thực thi. Xóa OR Response.response LIKE '%46104%' khỏi nó sẽ giảm thời gian xuống còn 0.140 giây. Bảng phản hồi chứa 288317 hàng và cột response.responses là cột TEXT() với chỉ mục FULLTEXT.

Cách tốt nhất để giảm thời gian thực hiện tìm kiếm này là gì? Tôi đã cố gắng sử dụng https://dba.stackexchange.com/questions/15214/why-is-like-more-than-4x-faster-than-match-against-on-a-fulltext-index-in-mysq câu trả lời này tuy nhiên khi tôi thực hiện:

SELECT responseID FROM 
(
SELECT * FROM responses 
WHERE requestID = 15000 
AND responseID != 84056 
) A 
WHERE MATCH(response) AGAINST('twisted'); 

tôi nhận được lỗi này:

Error Code: 1191. Can't find FULLTEXT index matching the column list

Trợ giúp sẽ được đánh giá cao!

EDIT 1:

Cố gắng @ Richard EB của truy vấn:

ALTER TABLE responses ADD FULLTEXT(response) 
288317 row(s) affected Records: 288317 Duplicates: 0 Warnings: 0 78.967 sec 

Tuy nhiên:

SELECT responseID FROM ( SELECT * FROM responses  WHERE requestID = 15000  AND responseID != 84056) A WHERE MATCH(response) AGAINST('twisted') LIMIT 0, 2000 
Error Code: 1191. Can't find FULLTEXT index matching the column list 0.000 sec 

Loại bỏ DISTINCT giảm thời gian thực hiện đến 0,952 giây tuy nhiên nó không lấy kết quả tôi cần.

EDIT 2:

Thực thi truy vấn này:

SELECT DISTINCT 
responses.requestID AS "Id" FROM responses WHERE MATCH(response) AGAINST('twisted') 

mất 0.062 giây.

Thực thi này:

SELECT DISTINCT responses.requestID 
    FROM responses 
WHERE (
    MATCH (Responses.response) AGAINST ('twisted' IN BOOLEAN MODE) 
) 
ORDER BY responses.requestID ASC 

chỉ mất 0.046 giây. Tuy nhiên, việc chọn từ Yêu cầu và tham gia Câu trả lời là điều làm chậm truy vấn. Tôi không chắc liệu điều đó có nghĩa là toàn bộ truy vấn phải được viết lại hoàn toàn để chọn từ Câu trả lời và tham gia Yêu cầu thay thế không?

EDIT 3:

Dưới đây là các chỉ số mà tôi có trên RequestsResponses bảng:

# Table, Non_unique, Key_name, Seq_in_index, Column_name, Collation, Cardinality, Sub_part, Packed, Null, Index_type, Comment, Index_comment 
    responses, 0, PRIMARY, 1, responseID, A, 288317, , , , BTREE, , 
    responses, 1, requestID, 1, requestID, A, 48052, , , YES, BTREE, , 
    responses, 1, response, 1, response, , 1, , , YES, FULLTEXT, , 
    responses, 1, response_2, 1, response, , 1, , , YES, FULLTEXT, , 
    responses, 1, response_3, 1, response, , 1, , , YES, FULLTEXT, , 

    # Table, Non_unique, Key_name, Seq_in_index, Column_name, Collation, Cardinality, Sub_part, Packed, Null, Index_type, Comment, Index_comment 
    requests, 0, PRIMARY, 1, requestID, A, 46205, , , , BTREE, , 
    requests, 1, supportstatusID, 1, supportstatusID, A, 14, , , YES, BTREE, , 
    requests, 1, twistedfish_userID, 1, twistedfish_userID, A, 344, , , YES, BTREE, , 
    requests, 1, customergroupID, 1, customergroupID, A, 198, , , , BTREE, , 
    requests, 1, userID, 1, userID, A, 1848, , , YES, BTREE, , 
    requests, 1, siteID, 1, siteID, A, 381, , , YES, BTREE, , 
    requests, 1, request, 1, subject, , 1, , , YES, FULLTEXT, , 
    requests, 1, request, 2, detail, , 1, , , YES, FULLTEXT, , 
    requests, 1, request, 3, ponumber, , 1, , , YES, FULLTEXT, , 

Trả lời

3

một tìm kiếm như sẽ đi qua tất cả các hồ sơ và thực hiện so sánh chuỗi không chính xác, mà là lý do tại sao nó quá chậm.

Lỗi mysql bạn đã dán cho biết cột được tham chiếu trong mệnh đề MATCH không có chỉ mục toàn văn (hoặc có, nhưng không phải vì nó được tham chiếu trong mệnh đề MATCH).

Giả sử bạn đang sử dụng MyISAM hoặc có MySQL 5,6 và InnoDB, hãy thử:

ALTER TABLE responses ADD FULLTEXT(response); 

Edit: trả lời (trong ý kiến): "Nếu có hai cột nêu trong báo cáo kết quả trận đấu, sau đó nên là một chỉ mục toàn văn trên cả hai cột đó, không phải hai chỉ mục toàn văn trên mỗi cột "

+0

Cảm ơn bạn, tôi đã thử rằng tuy nhiên nó không giải quyết được vấn đề. Tôi đã chỉnh sửa bài đăng gốc của mình. Vấn đề là, tìm kiếm LIKE mất một nửa thời gian mà MATCH ... tìm kiếm cũ tuy nhiên tôi giả định rằng bằng cách tối ưu hóa/cải thiện sau này, nó có thể nhanh hơn nhiều so với tìm kiếm LIKE. Tôi có đúng không? – Pawel

+0

Điều gì sẽ xảy ra khi bạn cố gắng: CHỌN * TỪ các câu trả lời CÓ PHÙ HỢP (phản hồi) CHỐNG LẠI ('xoắn') Nếu điều đó không hiệu quả, hãy thử: CÁC BẢNG bảng phản ứng ALTER TABLE ENABLE KEYS Nếu điều đó có hiệu quả, vấn đề là không phải với chỉ mục toàn văn, nhưng theo cách/thứ tự bạn đã viết truy vấn. –

+0

Cảm ơn, tôi đã chỉnh sửa bài đăng gốc của mình với các truy vấn và kết quả. – Pawel

Các vấn đề liên quan