2015-10-21 15 views
6

Ben Tahrik ORM üzerinde çalışan bir web sitesi üzerinde çalışmak ve bu sorgu var:MySQL Maç ... çok yavaş sorguya Karşı

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 

It: SQL aşağıdaki çevirir

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

SQL sorgusunu çalıştırırken Propel ve 7.020 saniye kullanarak web sitesine yüklemek için iyi bir 20 saniye sürer.

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 

yürütmek için 3,308 saniye sürer:

yerine aşağıdaki denedim. OR Response.response LIKE '%46104%''un çıkarılması, süreyi 0.140 saniyeye düşürür. Yanıtlar tablosu 288317 satır içerir ve yanıtlar. Yanıtlar sütunu FULLTEXT dizinine sahip bir TEXT() sütundur.

Bu aramanın yürütme süresini kısaltmanın en iyi yolu ne olurdu? Ben yürütmek zaman ancak bu https://dba.stackexchange.com/questions/15214/why-is-like-more-than-4x-faster-than-match-against-on-a-fulltext-index-in-mysq cevabını kullanarak denedi:

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

Yardım büyük takdir edilecektir:

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

bu hatayı olsun!

DÜZENLEME 1:

çalıştı @Richard EB sorgusu: Ancak

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

: DISTINCT Çıkarma

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 

ancak almak değil 0.952 saniyeye yürütme zamanı azaltır İhtiyacım olan sonuçlar.

DÜZENLEME 2:

bu sorguyu yürütülüyor:

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

0,062 saniye sürer.

bu yürütülüyor:

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

sadece 0.046 saniye sürer. Ancak, İstekler arasından seçim yapmak ve Yanıtları birleştirmek, sorguyu yavaşlatır. Bu, tüm sorgunun Yanıtlar arasından seçim yapmak ve bunun yerine İstekler'e katılmak için tamamen yeniden yazılması gerektiğinden emin değil mi?

DÜZENLEME 3: Burada

Ben Requests üzerindeki dizinleri ve Responses tablolar şunlardır:

# 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, , 

cevap

3

bir GİBİ arama her kaydın geçmesi ve kesin olmayan dize karşılaştırma yapacak, hangi bu yüzden bu kadar yavaş.

Yaptığınız mysql hatası, MATCH yan tümcesinde başvurulan sütunun tam metin dizinine sahip olmadığını gösterir (ya da yapar, ancak MATCH yan tümcesinde belirtildiği gibi değil).

ALTER TABLE responses ADD FULLTEXT(response); 

Düzenleme:: Cevap (yorumlarda):

Eğer MyISAM kullanarak veya MySQL 5.6 olması ve InnoDB, deneyeceğiz varsayarsak MAÇ açıklamada belirtilen iki sütun varsa ", daha sonra orada olmalı Bu sütunların her birinde bir tam metin dizini, her bir sütunda iki tam metin dizini değil "

+0

Teşekkür ederim, sorunu çözmedi ancak denedim. Orijinal gönderimi düzenledim. Sorun şu ki, LIKE aramasının yarısını alması gereken zaman ... YANLIŞTIRMA arama yapar, ancak bunu iyileştirerek/geliştirerek, LIKE aramasından çok daha hızlı olabilir. Doğrumuyum? Sadece çalıştığınızda – Pawel

+0

ne olur: Bu işe yaramazsa ('bükülmüş') KARŞI MAÇ (response) yanıtları SELECT *, deneyin: TABLO tablo yanıtları TUŞLARINA işliyor olursa , sorun olduğu ENABLE ALTER tam metin dizini ile değil, ama/sırada sorguyu yazdınız. –

+0

Teşekkürler, orijinal gönderiyi sorgular ve sonuçlar ile düzenledim. – Pawel