0

非常に遅い選択クエリがあり、それを高速化するために多くのことを試みましたが、実行にはまだ数かかります。表と私が試したことを説明します。このかなり単純なクエリを整理するためのより効率的な方法があるかどうか疑問に思っています。

約18000行あります。

クエリの説明

基本的に、ポジションはブローカーによって所有されているクライアントによって所有されているため、ポジションをブローカーにリンクするには、テーブルを調べます。対応するブローカーのポジションと、それらが を介して別のポジションにリンクされているかどうか、およびリンクされているポジション (存在する場合) を表示しています。clientscovered_positions

表の説明

  • positionsクライアントによって行われたすべての取引 (株式/オプション) が含まれています。PK (AI) がありますが、MySQL はそれを可能なインデックスpositionsIDとして認識していないようです。以下の結果を説明してください。
  • clientsすべてのクライアント情報 (顧客) が含まれています。clientsIDの外部キーであるPK (AI) を持っていますpositions
  • login_usersブローカー (従業員) が含まれます。asuser_idに外部キーであるPK (AI) を持っています。clientsbroker_id
  • covered_positions2 ~ 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

私が試したこと

  • 使用されていないクエリからすべての列を削除する
  • クエリをビューとして作成する
  • データベースの分析と最適化
  • サーバーの変更

どんなサポートも大歓迎です。

4

2 に答える 2

1

マイナーではありますが、括弧を使いすぎています...ここでは/結合から改訂されています

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 (残りのクエリ)

そして3番目に、あなたのテーブル「Covered_positions」は、各linked_id列にインデックスを持っていますか? 結合で使用できるインデックスがない場合、クエリがクロールされます。

最後に、対象となるポジション テーブルにクライアント ID がある場合は、それをインデックスの最初のフィールドとして絶対に追加し、結合にクライアント ID を含めます。この方法では、少なくとも最初にクライアントに結合し、次にそのクライアント内の位置。

于 2013-02-21T14:53:49.350 に答える
0

トリガーを使用して問題を解決できました。これらのコストのかかる OR を使用する代わりに、次を使用してfromが追加されたpositions場所link_idに、単に列を追加しました。idcovered_positions

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 万行に変えません。

于 2013-02-22T17:11:29.870 に答える