簡體   English   中英

MySQL查詢超級慢

[英]MySql Query Super Slow

我有以下查詢,它非常慢(僅4-5秒即可得到結果。我想知道是否有人可以通過此查詢來加快處理速度嗎?

謝謝!

SELECT
accounts.id AS account_id,
accounts. NAME AS account_name,
accounts.assigned_user_id account_id_owner,
users.user_name AS assigned_user_name,
opportunities_cstm.firstname_c, opportunities_cstm.lastname_c,
opportunities.`name`, TRIM(
    Concat(
        Ifnull(
            opportunities_cstm.firstname_c,
            ''
        ),
        ' ',
        Ifnull(
            opportunities_cstm.lastname_c,
            ''
        )
    )
) AS 'cfull' FROM
opportunities 
LEFT JOIN users ON opportunities.assigned_user_id = users.id 
LEFT JOIN accounts_opportunities ON opportunities.id = accounts_opportunities.opportunity_id 
LEFT JOIN accounts ON accounts_opportunities.account_id = accounts.id
LEFT JOIN opportunities_cstm ON opportunities.id = opportunities_cstm.id_c
WHERE
(
    (
        opportunities.sales_stage IN (
            'Prospecting',
            'Appointment Set',
            'MeetAndGreet',
            'Qualification',
            'Needs Analysis',
            'Locating Vehicle',
            'Demo',
            'Trade Evaluation',
            'Negotiation',
            'Manager T/O',
            'Write Up',
            'Credit App Submitted',
            'Pending Finance',
            'Loan Approval',
            'Deposit',
            'Delayed Decision',
            'Sold-Vehicle Ordered',
            'Sold-Pending Finance',
            'Sold/Pending Delivery',
            'Price Quoted',
            'Service Pending'
        )
    )
)
AND (
accounts_opportunities.deleted IS NULL
OR accounts_opportunities.deleted = 0
)
AND (
accounts.deleted IS NULL
OR accounts.deleted = 0
)
AND opportunities.deleted = 0
ORDER BY
opportunities.date_entered DESC,
opportunities.id DESC
LIMIT 0,21

這是來自同一查詢的說明:

╔═════════════╦════════════════════════╦════════╦══════════════════════════╦═════════════════════╦═════════╦════════════════════════════════════════════╦═══════╦═════════════════════════════╗
║ select_type ║         table          ║  type  ║      possible_keys       ║         key         ║ key_len ║                    ref                     ║ rows  ║            extra            ║
╠═════════════╬════════════════════════╬════════╬══════════════════════════╬═════════════════════╬═════════╬════════════════════════════════════════════╬═══════╬═════════════════════════════╣
║ simple      ║ opportunities          ║ range  ║ sales_stage, idx_deleted ║ sales_stage         ║      78 ║ null                                       ║ 25161 ║ Using where; Using filesort ║
║ simple      ║ users                  ║ eq_ref ║ PRIMARY, idx_id_deleted  ║ PRIMARY             ║     108 ║ version4.opportunities.assigned_user_id    ║     1 ║                             ║
║ simple      ║ accounts_opportunities ║ ref    ║ idx_oppid_del_accid      ║ idx_oppid_del_accid ║     111 ║ version4.opportunities.id                  ║     1 ║ Using where; Using index    ║
║ simple      ║ accounts               ║ eq_ref ║ PRIMARY,idx_accnt_id_del ║ PRIMARY             ║     108 ║ version4.accounts_opportunities.account_id ║     1 ║ Using where                 ║
║ simple      ║ opportunities_cstm     ║ eq_ref ║ PRIMARY                  ║ PRIMARY             ║     108 ║ version4.opportunities.id                  ║     1 ║                             ║
╚═════════════╩════════════════════════╩════════╩══════════════════════════╩═════════════════════╩═════════╩════════════════════════════════════════════╩═══════╩═════════════════════════════╝

我看到兩個問題。

首先,您使用兩個不同的WHERE (... IS NULL OR ... = 0)條件。 那些速度真是慢。 這是因為索引對於查找NULL值沒有用。 如果您可以消除那些deleted列中NULL的可能性,則可以通過將它們聲明為NOT NULL DEFAULT 0來將這些條件更改為WHERE ... = 0 這應該加快很多事情。 這是因為索引對於查找NULL值沒有用。

其次,您要創建一個很大的聯合結果集,然后對其進行排序以找到最新的項目。

在加入之前,您可以嘗試從“機會”表中預選擇項目。 做這樣的事情:

SELECT   whatever....
FROM (
         SELECT * 
           FROM opportunities
          WHERE opportunities.deleted = 0
            AND opportunities.sales_stage IN (
            'Prospecting',
            'Appointment Set',  etc etc  ...
            'Service Pending' )
       ORDER BY opportunities.date_entered DESC,
                opportunities.id DESC
          LIMIT 0,21
      ) opportunities 
LEFT JOIN users ON opportunities.assigned_user_id = users.id
...
ORDER BY
opportunities.date_entered DESC,
opportunities.id DESC
LIMIT 0,21

通過從聯接右側刪除一堆記錄來減少LEFT JOIN操作的基數,這很可能會加快處理速度。

請勿使用IN。 IN在mysql中工作緩慢,使用Exists

DROP TABLE IF EXISTS tempTable;
CREATE TEMPORARY TABLE tempTable ( sales_stage VARCHAR(50) NOT NULL );
insert into tempTable () values ('Prospecting'),('Appointment Set'),('MeetAndGreet'),...,('Service Pending');

SELECT
...
WHERE EXISTS(select sales_stage from tempTable where opportunities.sales_stage = sales_stage);

我不確定是否會有所改善,但是我會嘗試的是:

SELECT your_fields
FROM
  (SELECT * --or just the fields you need
   FROM
     opportunities
   WHERE
     opportunities.deleted = 0 AND
     opportunities.sales_stage IN (stage1, stage2, ...)
  ) opportunities1
  LEFT JOIN users ON opportunities1.assigned_user_id = users.id 
  LEFT JOIN accounts_opportunities ON opportunities1.id = ...etc...
WHERE
  (accounts_opportunities.deleted IS NULL
   OR accounts_opportunities.deleted = 0)
  AND (accounts.deleted IS NULL OR accounts.deleted = 0)
ORDER BY ...etc...

讓我知道它是否有任何改善(但也可能會更慢)。 另一個想法是將表格與所有需要過濾的階段一起使用:

CREATE TABLE filter_stage (
  stage varchar(255));

(255或嘗試匹配sales_stage的實際長度,最好也對這一列建立索引),在其中輸入所有要過濾的字符串:

INSERT INTO filter_stage VALUES ('Prospecting'), ('Appointment Set'), ('...'), ...

然后從第一個查詢中刪除IN子句,然后FROM變為:

FROM
  opportunities INNER JOIN filter_stage
  ON opportunities.sales_stage = filter_stage.stage
  LEFT JOIN ...

讓我知道它是否有效!

暫無
暫無

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

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