[英]Can this query be any faster?
我有以下查詢:
SELECT SQL_CALC_FOUND_ROWS *
FROM (
SELECT *
FROM
(
SELECT M.id, M.project_id, M.reply_toaddress as reply_toemailaddress, M.phone_no, M.subject,M.message, M.timestamp_received, M.done, M.postpone, "mail" AS type, M.firstname, M.prefix, M.surname
FROM messages M
LEFT JOIN link_projects_mailboxes LPMB
ON M.mailbox_id = LPMB.mailbox_id
WHERE M.main_message_id =0
AND LPMB.projects_id = 13 AND ( 0 OR (M.done = 0 AND M.postpone = 0 )) AND M.status = 0
GROUP BY M.id
) M
UNION
(
SELECT C.id, C.project_id, C.reply_toemailaddress, C.phone_no, C.subject,C.message, C.timestamp_received, done, postpone, "call" AS type , C.firstname, C.prefix, C.surname
FROM calls C
WHERE 1
AND projects_id = 13 AND ( 0 OR (C.done = 0 AND C.postpone = 0 )) AND C.status = 0
)
) x ORDER BY `timestamp_received` asc LIMIT 30
問題是此查詢正在700.000行上運行,其數據為19.2GB。 查詢運行大約3分鍾。
如果我解釋該查詢,則會收到以下結果:
你們有什么建議嗎?
編輯:顯示創建表:
CREATE TABLE `messages` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`mailbox_id` int(11) NOT NULL,
`submessage_of` int(11) NOT NULL,
`main_message_id` int(11) NOT NULL,
`project_id` int(11) NOT NULL COMMENT 'Takes project from afasmssql_sync DB',
`categorie_id` int(11) NOT NULL,
`call_id` int(11) NOT NULL,
`to` text NOT NULL,
`cc` text NOT NULL,
`bcc` text NOT NULL,
`message_id` varchar(255) NOT NULL,
`bytes` int(11) NOT NULL,
`from` varchar(255) NOT NULL,
`sender` varchar(255) NOT NULL,
`reply_toaddress` varchar(255) NOT NULL,
`reply_toemailaddress` varchar(255) NOT NULL,
`subject` varchar(255) NOT NULL,
`order_id` int(10) NOT NULL DEFAULT '0',
`order_location` varchar(255) NOT NULL,
`firstname` varchar(200) NOT NULL,
`prefix` varchar(50) NOT NULL,
`surname` varchar(200) NOT NULL,
`emailaddress` varchar(200) NOT NULL,
`phone_no` varchar(255) NOT NULL,
`zipcode` varchar(6) NOT NULL,
`house_no` varchar(6) NOT NULL,
`house_no_add` varchar(50) NOT NULL,
`street` varchar(200) NOT NULL,
`city` varchar(200) NOT NULL,
`country` varchar(50) NOT NULL,
`language` varchar(50) NOT NULL,
`message` longtext NOT NULL,
`message_plain` longtext NOT NULL,
`message_stripped` longtext NOT NULL,
`quality_status` tinyint(1) NOT NULL,
`quality_by` int(11) NOT NULL,
`quality_date` datetime NOT NULL,
`done` tinyint(1) NOT NULL,
`done_date` datetime NOT NULL,
`done_by` int(11) NOT NULL,
`postpone` tinyint(1) NOT NULL,
`status` int(11) NOT NULL,
`manually` tinyint(1) NOT NULL,
`timestamp_received` datetime NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `mailbox_id` (`mailbox_id`),
KEY `submessage_of` (`submessage_of`),
KEY `main_message_id` (`main_message_id`),
KEY `subject` (`subject`),
KEY `done` (`done`),
KEY `postpone` (`postpone`),
KEY `status` (`status`),
KEY `project_id` (`project_id`),
KEY `categorie_id` (`categorie_id`),
KEY `call_id` (`call_id`),
KEY `done_date` (`done_date`),
KEY `timestamp_received` (`timestamp_received`),
KEY `from` (`from`),
KEY `reply_toemailaddress` (`reply_toemailaddress`),
KEY `timestamp` (`timestamp`),
FULLTEXT KEY `message` (`message`)
) ENGINE=MyISAM AUTO_INCREMENT=685579 DEFAULT CHARSET=utf8
CREATE TABLE `link_projects_mailboxes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`projects_id` int(11) NOT NULL,
`mailbox_id` int(11) NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `projects_id` (`projects_id`,`mailbox_id`)
) ENGINE=MyISAM AUTO_INCREMENT=156 DEFAULT CHARSET=latin1
CREATE TABLE `calls` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`actionline_id` int(11) NOT NULL,
`projects_id` int(11) NOT NULL,
`project_id` int(11) NOT NULL COMMENT 'Takes project from afasmssql_sync DB',
`categorie_id` int(11) NOT NULL,
`call_direction` varchar(255) NOT NULL,
`subject` varchar(255) NOT NULL,
`order_id` int(10) NOT NULL DEFAULT '0',
`order_location` varchar(255) NOT NULL,
`firstname` varchar(200) NOT NULL,
`prefix` varchar(50) NOT NULL,
`surname` varchar(200) NOT NULL,
`reply_toemailaddress` varchar(200) NOT NULL,
`phone_no` varchar(255) NOT NULL,
`zipcode` varchar(6) NOT NULL,
`house_no` varchar(6) NOT NULL,
`house_no_add` varchar(50) NOT NULL,
`street` varchar(200) NOT NULL,
`city` varchar(200) NOT NULL,
`country` varchar(50) NOT NULL,
`language` varchar(50) NOT NULL,
`message` longtext NOT NULL,
`done` tinyint(1) NOT NULL,
`done_date` datetime NOT NULL,
`done_by` int(11) NOT NULL,
`postpone` tinyint(1) NOT NULL,
`status` int(11) NOT NULL,
`timestamp_received` datetime NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `mailbox_id` (`actionline_id`),
KEY `subject` (`subject`),
KEY `done` (`done`),
KEY `postpone` (`postpone`),
KEY `status` (`status`),
KEY `project_id` (`project_id`),
KEY `projects_id` (`projects_id`),
FULLTEXT KEY `message` (`message`)
) ENGINE=MyISAM AUTO_INCREMENT=8941 DEFAULT CHARSET=utf8
編輯:基於草莓的解釋答案:
因此,為了使內容更具可讀性,讓我們從此查詢開始,然后在該查詢上運行EXPLAIN ...
SELECT SQL_CALC_FOUND_ROWS *
FROM
( SELECT M.id
, M.project_id
, M.reply_toaddress as reply_toemailaddress
, M.phone_no
, M.subject
, M.message
, M.timestamp_received
, M.done
, M.postpone
, "mail" type
, M.firstname
, M.prefix
, M.surname
FROM messages M
JOIN link_projects_mailboxes LPMB
ON LPMB.mailbox_id = M.mailbox_id
WHERE M.main_message_id = 0
AND LPMB.projects_id = 13
AND M.done = 0
AND M.postpone = 0
AND M.status = 0
UNION
SELECT C.id
, C.project_id
, C.reply_toemailaddress
, C.phone_no
, C.subject
, C.message
, C.timestamp_received
, C.done
, C.postpone
, "call" type
, C.firstname
, C.prefix
, C.surname
FROM calls C
WHERE C.projects_id = 13
AND C.done = 0
AND C.postpone = 0
AND C.status = 0
) x
ORDER
BY timestamp_received ASC
LIMIT 30;
解釋相同:
+------+--------------+------------+------+------------------+-------------+---------+---------------------+-------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+--------------+------------+------+------------------+-------------+---------+---------------------+-------+----------------+
| 1 | PRIMARY | <derived2> | ALL | (NULL) | (NULL) | (NULL) | (NULL) | 218 | Using filesort |
+------+--------------+------------+------+------------------+-------------+---------+---------------------+-------+----------------+
| 2 | DERIVED | LPMB | ref | projects_id | projects_id | 4 | | 1 | Using index |
+------+--------------+------------+------+------------------+-------------+---------+---------------------+-------+----------------+
| 2 | DERIVED | M | ref | mailbox_id, | mailbox_id | 4 | ccc.LPMB.mailbox_id | 7,735 | Using where |
| | | | | main_message_id, | | | | | |
| | | | | done, | | | | | |
| | | | | postpone, | | | | | |
| | | | | status | | | | | |
+------+--------------+------------+------+------------------+-------------+---------+---------------------+-------+----------------+
| 3 | UNION | C | ref | done, | done | 1 | | 4 | Using where |
| | | | | postpone, | | | | | |
| | | | | status, | | | | | |
| | | | | projects_id | | | | | |
+------+--------------+------------+------+------------------+-------------+---------+---------------------+-------+----------------+
|(NULL)| UNION RESULT | <union2,3> | ALL | (NULL) | (NULL) | (NULL) | (NULL) | (NULL)| |
+------+--------------+------------+------+------------------+-------------+---------+---------------------+-------+----------------+
由於兩個內部SELECTs
沒有公共行,因此將UNION
更改為UNION ALL
。 這樣可以節省重復的通行證。 運行它們中的每一個,看看哪個較慢; 然后我們可以專注於它。
這些“復合”索引可以幫助它運行得更快:
M: INDEX(mailbox_id, message_id, done, postpone, status) -- in any order
calls: INDEX(projects_id, done, postpone, status) -- in any order
如果您不需要SQL_CALC_FOUND_ROWS
,則速度會更快:
( SELECT ... FROM M ... ORDER BY ... LIMIT 30 )
UNION ALL
( SELECT ... FROM M ... ORDER BY ... LIMIT 30 )
ORDER BY ... LIMIT 30; -- yes, repeated again
它將需要合適的索引,可能是上面建議的索引,並在末尾添加了timestamp_received
。 並且實際上無用的JOIN LPMB
應該替換為AND EXISTS ( SELECT ... FROM LPMB ... )
如果要使用OFFSET
分頁,則UNION
+ LIMIT
技巧會變得更加復雜,但仍然可以實現。
無關:
擺脫各個標志的索引; 他們通常是無用的。
您應該從MyISAM遷移到InnoDB。 FULLTEXT
(略有不同)在更高版本中可用。
@dacrovinunghi-MySQL沒有“位圖”索引類型。
WHERE 1
和0 OR
來自動態構建WHERE
子句,但沒有花時間保持它的清潔。 我更喜歡構建一個將被AND'd
與的子句數組,然后將其內implode
。 或者,如果沒有,則一起避開WHERE
。
這可能是較好的去除“完成”(ETC)從表中的項目。 這樣可以省去WHERE
那一部分,並縮小桌子,使其更緊湊,更高效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.