简体   繁体   English

如何加速复杂的MYSQL查询?

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

I have the following MYSQL query in a Cold Fusion Component being called from a ColdFusion website. 我从ColdFusion网站调用Cold Fusion组件中有以下MYSQL查询。 I have a custom take that basically builds a boolean query for the following fields: "PlaceName,Country,Adm1,adm2,adm3,locality". 我有一个自定义的,基本上为以下字段构建一个布尔查询:“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>

There are 624227 records in the database. 数据库中有624227条记录。 If I do a search for Chappaqua, the actually SQL that gets run is as follows: 如果我搜索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

I know it is ugly and complex. 我知道它很丑陋而复杂。 It takes about 1836ms to run. 运行大约需要1836毫秒。 Is there any better way to write the query or code so that it speeds up the returned data in under a second? 有没有更好的方法来编写查询或代码,以便在一秒钟内加速返回的数据?

Here is the Explain on the SQL: 这是关于SQL的说明: SQL EXPLAIN

The problem is that the engine is doing a full table scan of the table, then sorting the results for the group by . 问题是引擎正在对表进行全表扫描,然后对group by排序。

The full table scan almost seems necessary because of the like s: 全表扫描几乎是必要的,因为like的:

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

The issue is that an index on PlaceName cannot be used, because the initial characters are not fixed. 问题是无法使用PlaceName的索引,因为初始字符不是固定的。

So . 所以。 . . Can you remove the group by ? 你可以删除该group by吗? You can at least replace it with distinct , although I don't think that would affect the query plan. 你至少可以用distinct替换它,虽然我认为这不会影响查询计划。 Do you have an index on place_cats(placeId, catId) ? 你有关于place_cats(placeId, catId)的索引吗? That would at least prevent the query from reading the category table so it could just do index lookups. 这至少会阻止查询读取类别表,因此它可以只进行索引查找。

Can you limit the search only to words at the beginning of the fields? 你能将搜索限制在字段开头的单词吗?

The only other alternative that I can think of is to switch to using a full text index in MySQL. 我能想到的唯一另一种选择是切换到在MySQL中使用全文索引。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM