簡體   English   中英

來自3個左聯接的極慢的選擇查詢

[英]Extremely slow select query from 3 left joins

我的選擇查詢速度很慢,並且我嘗試了很多方法來加快它的速度,但是執行它仍然需要幾分鍾 我將解釋表格和我嘗試過的內容。 我想知道是否有更有效的方法來組織此相當簡單的查詢。

大約有18000行。

查詢解釋

本質上, 頭寸經紀人擁有的客戶所有,因此要將該頭寸鏈接到經紀人,我們要通過“ clients表。 我正在顯示與相應經紀人的職位,以及它們是否通過covered_positions鏈接到另一個職位,以及鏈接了哪個職位(如果有)。

表格說明

  • positions包含客戶完成的所有交易(股票/期權)。 它具有PK positionsID (AI),但MySQL似乎沒有將其識別為可能的索引 在下面解釋結果。
  • clients包含所有客戶信息(客戶)。 它具有PK clientsID (AI),它是positions的外鍵。
  • login_users包含代理(員工)。 它具有PK user_id (AI),它是clients的外鍵,作為broker_id
  • covered_positions包含2-5個位置之間的鏈接(不是超鏈接)。 它具有PK covered_id (AI)。 linked_id*列是已鏈接在一起的positionsID

查詢

delimiter $$

CREATE VIEW `main_join3` AS 
select `positions`.`id` AS `positionsID`,
`positions`.`order_list` AS `order_list`,
`positions`.`client_id` AS `client_id`,
`positions`.`client_name` AS `client_name`,
`positions`.`broker_name` AS `pos_broker_name`,
`positions`.`account_status` AS `pos_account_status`,
`positions`.`cost_basis` AS `cost_basis`,
`positions`.`cost_per_share` AS `cost_per_share`,
`positions`.`security` AS `security`,
`positions`.`security_type` AS `security_type`,
`positions`.`strike_price` AS `strike_price`,
`positions`.`option_type` AS `option_type`,
`positions`.`exp_month` AS `exp_month`,
`positions`.`exp_year` AS `exp_year`,
`positions`.`exp_date` AS `exp_date`,
`positions`.`buy_shares` AS `buy_shares`,
`positions`.`buy_date` AS `buy_date`,
`positions`.`buy_price` AS `buy_price`,
`positions`.`buy_commission` AS `buy_commission`,
`positions`.`buy_misc` AS `buy_misc`,
`positions`.`buy_cost` AS `buy_cost`,
`positions`.`sell_shares` AS `sell_shares`,
`positions`.`sell_date` AS `sell_date`,
`positions`.`sell_price` AS `sell_price`,
`positions`.`sell_commission` AS `sell_commission`,
`positions`.`sell_misc` AS `sell_misc`,
`positions`.`sell_cost` AS `sell_cost`,
`positions`.`loss` AS `loss`,
`positions`.`profit` AS `profit`,
`positions`.`funds_in_out` AS `funds_in_out`,
`positions`.`funds_in` AS `funds_in`,
`positions`.`funds_out` AS `funds_out`,
`positions`.`stop_order` AS `stop_order`,
`positions`.`notes` AS `notes`,
`positions`.`orange_highlight` AS `orange_highlight`,
`positions`.`date_created` AS `pos_date_created`,
`positions`.`date_updated` AS `pos_date_updated`,
`positions`.`created_by_id` AS `pos_cb_id`,
`positions`.`created_by_name` AS `pos_cb_name`,
`clients`.`id` AS `clientsID`,
`clients`.`broker_id` AS `broker_id`,
`clients`.`account_status` AS `clients_account_status`,
`login_users`.`user_id` AS `user_id`,
`login_users`.`user_level` AS `user_level`,
`login_users`.`username` AS `username`,
`login_users`.`name` AS `name`,
`covered_positions`.`id` AS `covered_id`,
`covered_positions`.`linked_id1` AS `linked_id1`,
`covered_positions`.`linked_id2` AS `linked_id2`,
`covered_positions`.`linked_id3` AS `linked_id3`,
`covered_positions`.`linked_id4` AS `linked_id4`,
`covered_positions`.`linked_id5` AS `linked_id5` 
from (((`positions` 
left join `clients` 
on((`positions`.`client_id` = `clients`.`id`))) 
left join `login_users` 
on((`clients`.`broker_id` = `login_users`.`user_id`))) 
left join `covered_positions` 
on(((`positions`.`id` = `covered_positions`.`linked_id1`) 
or (`positions`.`id` = `covered_positions`.`linked_id2`) 
or (`positions`.`id` = `covered_positions`.`linked_id3`) 
or (`positions`.`id` = `covered_positions`.`linked_id4`) 
or (`positions`.`id` = `covered_positions`.`linked_id5`))))$$

說明結果

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  positions   ALL NULL    NULL    NULL    NULL    18070   
1   SIMPLE  clients eq_ref  PRIMARY PRIMARY 4   blackri_posting.positions.client_id 1   
1   SIMPLE  login_users eq_ref  PRIMARY,user_id PRIMARY 4   blackri_posting.clients.broker_id   1   
1   SIMPLE  covered_positions   ALL NULL    NULL    NULL    NULL    214

我嘗試過的

  • 從查詢中刪除所有未使用的列
  • 創建查詢作為視圖
  • 分析和優化數據庫
  • 更換服務器

非常感謝任何支持。

雖然較小,但是您仍然有可能過度使用括號...這里是從/聯接處修改的

from 
   positions
      left join clients
         ON positions.client_id = clients.id 
         left join login_users
            ON clients.broker_id = login_users.user_id
      left join covered_positions
         ON  positions.id = covered_positions.linked_id1
         or  positions.id = covered_positions.linked_id2  
         or  positions.id = covered_positions.linked_id3 
         or  positions.id = covered_positions.linked_id4
         or  positions.id = covered_positions.linked_id5

其次,僅出於笑容,請嘗試在查詢中添加MySQL關鍵字“ STRAIGHT_JOIN” ...

SELECT STRAIGHT_JOIN(查詢的其余部分)

第三,您的表“ Covered_positions”在每個linked_id列上都有索引嗎? 如果無法在聯接上使用索引,則將使查詢爬網。

最后,如果您覆蓋的頭寸表具有客戶ID,則我將其絕對添加為索引中的第一個字段,並在連接中包括客戶ID ...這樣,至少您將首先加入該客戶,然后該客戶中的職位。

我設法使用觸發器解決了這個問題。 我沒有使用那些昂貴的OR,而只是在稱為link_id positions添加了一個列,其中通過使用以下方法添加了covered_positionsid

DELIMITER $$
CREATE TRIGGER covereds_after_insert
    AFTER INSERT ON covered_positions
    FOR EACH ROW
BEGIN
    UPDATE positions
    SET link_id = NEW.id 
    WHERE positions.id 
    IN (NEW.linked_id1, NEW.linked_id2, NEW.linked_id3, NEW.linked_id4, NEW.linked_id5);
END
$$

DELIMITER $$
CREATE TRIGGER covereds_after_delete
    AFTER DELETE ON covered_positions
    FOR EACH ROW
BEGIN
    UPDATE positions
    SET link_id = NULL
    WHERE positions.id 
    IN (OLD.linked_id1, OLD.linked_id2, OLD.linked_id3, OLD.linked_id4, OLD.linked_id5);
END
$$

這樣,查詢不會將18,000行變成大約400萬行。

暫無
暫無

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

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