簡體   English   中英

結合兩個非常快的查詢時,MySQL慢查詢

[英]MySQL slow query when combining two very fast queries

我有兩個運行非常快的MySQL查詢,但是當我將它們組合時,新查詢非常慢。

快速(<1秒,15個結果):

SELECT DISTINCT 
Id, Name, Company_Id
FROM people
where Company_Id in (5295, 1834)
and match(Locations) against('austin')

快速(<1秒,2970個結果):

select distinct Company_Id from technologies
    where match(Name) against('elastic')
      and Company_Id is not null

當我像這樣結合兩者時:

SELECT DISTINCT Id, Name, Company_Id
FROM people
where Company_Id in
    ( select Company_Id from technologies
        where match(Name) against('elastic')
          and Company_Id is not null
    )
  and match(Locations) against('austin')

結果查詢需要2分鍾以上才能完成。 它有278行命中。

我嘗試過幾種方式重寫慢速查詢。 另一個例子是這樣的:

SELECT DISTINCT 
`Extent1`.`Id`, `Extent1`.`Name`, `Extent1`.`Company_Id`
FROM `people` AS `Extent1` 
INNER JOIN `technologies` AS `Extent2`
     ON (`Extent1`.`Company_Id` = `Extent2`.`Company_Id`)
WHERE (`Extent1`.`Company_Id` IS NOT NULL) 
 AND ((match(`Extent1`.`Locations`) against('austin')) 
 AND  (match(`Extent2`.`Name`) against('elastic')))

我在Windows上使用MySQL 5.7。 我在“名稱”和“位置”列上有全文索引。 我的InnoDB緩沖區使用率從未超過40%。 我嘗試使用MySQL工作台查看執行計划,但顯示“說明數據不可用於語句”

如果您看到我可以改進或嘗試的任何內容,請告訴我。 謝謝。

IN ( SELECT ... )的優化很差,至少在舊版本的MySQL中是如此。 您使用什么版本?

當使用FULLTEXT索引( MATCH... )時,如果可能的話,首先執行該部分。 這是因為幾乎總是FT查找比其他任何事物都快。

但是,當使用兩個全文查詢時,它會選擇一個,然后不能在另一個上使用全文。

這是一種可能的解決方法:

  • 有一個額外的表格進行搜索。 它包括NameLocations
  • FULLTEXT(Name, Locations)
  • MATCH (Name, Locations) AGAINST ('+austin +elastic' IN BOOLEAN MODE)

如有必要, AND用一些東西來驗證它是否不是,例如,找到一個名為“奧斯汀”的人。

另一種可能性:

5.7(或5.6?) 可以通過在子查詢上創建索引來優化此功能:

SELECT ...
    FROM ( SELECT Company_Id FROM ... MATCH(Name) ... ) AS x
    JOIN ( SELECT Company_Id FROM ... MATCH(Locations) ... ) AS y
        USING(Company_id);

提供EXPLAIN ; 我希望看到<auto-key>

測試一下。 如果“快速”,則可能需要添加另一個JOIN和/或WHERE (我不清楚您的最終查詢需要是什么。)

使用from子句中的子查詢編寫查詢:

select distinct p.Id, p.Name, p.Company_Id
from people p join
     (select Company_Id
      from technologies
      where match(Name) against('elastic') and Company_Id is not null
     ) t
     on p.Company_Id = t.Company_Id
where match(p.Locations) against ('austin');

我懷疑您的數據結構有問題。 您應該有一個CompanyLocations表,而不是在表的列表中存儲位置。

暫無
暫無

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

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