簡體   English   中英

如何加速復雜的MYSQL查詢?

[英]How to speed up a complex MYSQL Query?

我從ColdFusion網站調用Cold Fusion組件中有以下MYSQL查詢。 我有一個自定義的,基本上為以下字段構建一個布爾查詢:“PlaceName,Country,Adm1,adm2,adm3,locality”。

<!--- SEARCH PLACES 2--->
<cffunction name="searchPlaces_full" access="public" returntype="query">
    <cfargument name="q" type="string" required="yes">


    <CF_BOOLSEARCH searchterm="#arguments.q#" field="PlaceName,Country,Adm1,adm2,adm3,locality " booloperator="and">
    <cfquery name="GetPlaces" datasource="#application.settings.dsn#">
    SELECT 
        places.CatID,
        places.PlaceName,
        places.PlaceID,
        places.Address1,
        places.PostalCode,
        places.Locality,
        places.Address2,
        places.ImageThumb,
        places.Adm1,
        places.Country,
        places.Adm2,
        places.Adm3,
        places.contributorid,
        places.lng,
        places.lat,
        places.verified,
        places.verified_by,
        places.verified_date
    FROM places INNER JOIN places_cats ON places.PlaceID = places_cats.PlaceID
    WHERE  
    <cfif len(trim(arguments.q))>
    (#PreserveSingleQuotes(boolsearch)#)
    <cfelse>
    1=0
    </cfif>
    AND places_cats.CATID IN (#arguments.categories#)
    GROUP BY 
        places.CatID,
        places.PlaceName,
        places.PlaceID,
        places.Address1,
        places.PostalCode,
        places.Locality,
        places.Address2,
        places.ImageThumb,
        places.Adm1,
        places.Country,
        places.Adm2,
        places.Adm3,
        places.contributorid,
        places.lng,
        places.lat,
        places.verified,
        places.verified_by,
        places.verified_date
        ORDER BY PlaceName
        </cfquery>


    <cfreturn getPlaces>
</cffunction>

數據庫中有624227條記錄。 如果我搜索Chappaqua,實際運行的SQL如下:

       SELECT 
        places.CatID,
        places.PlaceName,
        places.PlaceID,
        places.Address1,
        places.PostalCode,
        places.Locality,
        places.Address2,
        places.ImageThumb,
        places.Adm1,
        places.Country,
        places.Adm2,
        places.Adm3,
        places.contributorid,
        places.lng,
        places.lat,
        places.verified,
        places.verified_by,
        places.verified_date
    FROM places INNER JOIN places_cats ON places.PlaceID = places_cats.PlaceID
    WHERE  

    (((PlaceName LIKE '%chappaqua%') OR (Country LIKE '%chappaqua%') OR (Adm1 LIKE '%chappaqua%') OR (adm2 LIKE '%chappaqua%') OR (adm3 LIKE '%chappaqua%') OR (locality  LIKE '%chappaqua%')))

    AND places_cats.CATID IN (1,21,15,32,16,26,29,27,28,25,75,89,38,5,36,88,87,31,33,24,35,37,90,39,40,34,30,9,8,7,11,20,19,96,97,95,13,17,14,12,3,2,4,84,85,86)
    GROUP BY 
        places.CatID,
        places.PlaceName,
        places.PlaceID,
        places.Address1,
        places.PostalCode,
        places.Locality,
        places.Address2,
        places.ImageThumb,
        places.Adm1,
        places.Country,
        places.Adm2,
        places.Adm3,
        places.contributorid,
        places.lng,
        places.lat,
        places.verified,
        places.verified_by,
        places.verified_date
        ORDER BY PlaceName

我知道它很丑陋而復雜。 運行大約需要1836毫秒。 有沒有更好的方法來編寫查詢或代碼,以便在一秒鍾內加速返回的數據?

這是關於SQL的說明: SQL EXPLAIN

問題是引擎正在對表進行全表掃描,然后對group by排序。

全表掃描幾乎是必要的,因為like的:

(((PlaceName LIKE '%chappaqua%') OR (Country LIKE '%chappaqua%') OR (Adm1 LIKE '%chappaqua%') OR (adm2 LIKE '%chappaqua%') OR (adm3 LIKE '%chappaqua%') OR (locality  LIKE '%chappaqua%')))

問題是無法使用PlaceName的索引,因為初始字符不是固定的。

所以。 你可以刪除該group by嗎? 你至少可以用distinct替換它,雖然我認為這不會影響查詢計划。 你有關於place_cats(placeId, catId)的索引嗎? 這至少會阻止查詢讀取類別表,因此它可以只進行索引查找。

你能將搜索限制在字段開頭的單詞嗎?

我能想到的唯一另一種選擇是切換到在MySQL中使用全文索引。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM