簡體   English   中英

使用子查詢優化 SQL 查詢

[英]Optimizing SQL query with sub queries

我有一個試圖優化的 SQL 查詢,我可以通過各種方式將時間從超過 5 秒減少到大約 1.3 秒,但不能再進一步了。 我想知道是否有人能夠提出進一步的改進建議。

解釋圖顯示了一個完整的掃描:解釋圖

解釋表將為您提供更多詳細信息:解釋表

查詢已簡化並顯示如下 - 僅供參考,我使用的是 MySQL 5.6

select * from (
  select 
    @row_num := if(@yacht_id = yacht_id and @charter_type = charter_type and @start_base_id = start_base_id and @end_base_id = end_base_id, @row_num +1, 1) as row_number,
    @yacht_id := yacht_id as yacht_id, 
    @charter_type := charter_type as charter_type,
    @start_base_id := start_base_id as start_base_id,
    @end_base_id := end_base_id as end_base_id,
    model, offer_type, instant, rating, reviews, loa, berths, cabins, currency, list_price, list_price_per_day, 
    discount, client_price, client_price_per_day, days, date_from, date_to, start_base_city, end_base_city, start_base_country, end_base_country, 
    service_binary, product_id, ext_yacht_id, main_image_url
  from (
    select
      offer.yacht_id, offer.charter_type, yacht.model, offer.offer_type, offer.instant, yacht.rating, yacht.reviews, yacht.loa, 
      yacht.berths, yacht.cabins, offer.currency, offer.list_price, offer.list_price_per_day, 
      offer.discount, offer.client_price, offer.client_price_per_day, offer.days, date_from, date_to,
      offer.start_base_city, offer.end_base_city, offer.start_base_country, offer.end_base_country,
      offer.service_binary, offer.product_id, offer.start_base_id, offer.end_base_id,
      yacht.ext_yacht_id, yacht.main_image_url
    from website_offer as offer
    join website_yacht as yacht
      on offer.yacht_id = yacht.yacht_id, 
    (select @yacht_id:='') as init
    where date_from > CURDATE() 
      and date_to <= CURDATE() + INTERVAL 3 MONTH
      and days = 7
    order by offer.yacht_id, charter_type, start_base_id, end_base_id, list_price_per_day asc, discount desc
  ) as filtered_offers
) as offers
where row_number=1;

謝謝,戈皮

UPDATE

我不得不放棄一些性能改進,並用新的 select 替換了原來的 select。 選擇查詢實際上是由后端根據設置的過濾條件動態構建的。 因此,最內層 select 的 where 子句可以擴展很多。 但是,如果沒有設置過濾器,這是默認選擇,並且是需要明顯長於 1 秒的版本。

以文本形式解釋 - 不是很漂亮,因為我不知道如何格式化表格,但這里是:

1 PRIMARY ref <auto_key0> <auto_key0> 9 const 10
2 全部派生 385967
3 DERIVED system 1 Using filesort 3 DERIVED offer ref idx_yachtid,idx_search,idx_dates idx_dates 5 const 385967 Using index condition; 使用 where 3 DERIVED 游艇 eq_ref PRIMARY,id_UNIQUE PRIMARY 4 游艇charter.offer.yacht_id 1
4 DERIVED 未使用表

子選擇從來都不是很好,你應該在這里注冊: https : //www.eversql.com/

運行它,它將為您提供此查詢所需的所有正確索引和優化。

您仍然可以使用一些優化。 考慮到子查詢返回 5000 行,您只能為其使用索引。

首先將謂詞改寫為:

select *
from website_offer
where date_from >= CURDATE() + INTERVAL 1 DAY -- rephrased here
  and date(date_to) <= CURDATE() + INTERVAL 3 MONTH
  and days = 7
order by yacht_id, charter_type, list_price_per_day asc, discount desc
limit 5000    

然后,如果添加以下索引,性能可能會提高:

create index ix1 on website_offer (days, date_from, date_to);

暫無
暫無

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

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