[英]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.