[英]Optimising a large SELECT/JOIN query with millions of rows
我對 MySQL 5.7 有以下查詢,無論我用它做什么,它都運行大約一分鍾,我試圖讓它運行得更快(最好將性能降低到幾秒鍾)。 這些表中的粗略數據量是 200 萬個動作、9 萬個會話和 10 萬個配置文件。
select
a.id as `action_id`,
a.type as `event_type`,
p.ip_address as `ip_address`,
p.browser_string as `browser_string`,
p.ua_device_type,
p.ua_os_family,
p.ua_os_name,
p.ua_type,
p.ua_family,
p.ua_version,
p.ipuas_hash,
s.session_string,
s.traffic_source,
s.org_traffic_source,
a.datetime as `timestamp`
from is_action as a
join is_session as s on a.session_id=s.id
join is_profile as p on s.profile_id=p.id
使用下表(刪除了一些不相關的字段):
CREATE TABLE `is_profile` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ip_address` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`browser_string` text COLLATE utf8_unicode_ci,
`ua_device_type` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`ua_os_family` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`ua_os_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`ua_type` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`ua_family` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`ua_version` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`ipuas_hash` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`session_count` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`) USING BTREE,
KEY `user_id` (`user_id`) USING BTREE,
KEY `ua_type` (`ua_type`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `is_session` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`profile_id` int(11) NOT NULL DEFAULT '0',
`traffic_source` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`session_string` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`datetime` datetime DEFAULT NULL,
`session_length` int(11) NOT NULL DEFAULT '0',
`org_traffic_source` mediumtext COLLATE utf8_unicode_ci,
`org_page` mediumtext COLLATE utf8_unicode_ci,
`action_count` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `comp_profile` (`profile_id`,`id`) USING BTREE,
KEY `profile_id` (`profile_id`) USING BTREE,
KEY `datetime` (`datetime`) USING BTREE,
KEY `traffic_source` (`traffic_source`) USING BTREE,
KEY `session_length` (`session_length`) USING BTREE,
CONSTRAINT `fk_profile` FOREIGN KEY (`profile_id`) REFERENCES `is_profile` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `is_action` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`session_id` int(11) NOT NULL,
`type` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`details` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`datetime` datetime NOT NULL,
`weight` int(11) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `comp_session` (`session_id`,`id`) USING BTREE,
KEY `session_id` (`session_id`) USING BTREE,
KEY `datetime` (`datetime`) USING BTREE,
CONSTRAINT `fk_session` FOREIGN KEY (`session_id`) REFERENCES `is_session` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
我嘗試了不同類型的連接,強制索引並在相關字段上添加更多索引,甚至增加了數據庫的 RAM 和 CPU,但似乎沒有任何東西可以減少查詢時間。 我還在下面包含了EXPLAIN
的屏幕截圖(被屏蔽的部分是敏感信息)。
任何幫助將不勝感激。
**編輯:表和補充之間**增加外鍵關系的EXPLAIN
像我忘了補充。
您需要在連接中使用的 FK 上定義外鍵約束。
您似乎忘記包含解釋計划。
順便說一句,您的獨特約束並沒有取得多大成就,因為它們包括根據定義已經獨一無二的 PK
(不是答案,而是對 JSBach 的冗長回復。)
這是一個奇怪的組合
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `comp_session` (`session_id`,`id`) USING BTREE,
KEY `session_id` (`session_id`) USING BTREE,
如果您希望session_id
是唯一的,那么您就失敗了。 讓它獨一無二:
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `comp_session` (`session_id`) USING BTREE,
-- redundant: KEY `session_id` (`session_id`) USING BTREE,
在這一點上,為什么不將session_id
提升為 PK?
回到 UNIQUE ( session_id
, id
) -- 因為id
已經because of the PK, this declaration provides _no_ useful uniqueness constraint. If it is primarily designed to be
被聲明為 UNIQUE, because of the PK, this declaration provides _no_ useful uniqueness constraint. If it is primarily designed to be
because of the PK, this declaration provides _no_ useful uniqueness constraint. If it is primarily designed to be
KEY(session_id, id) , then it is redundant with
KEY(session_id)` , then it is redundant with
; 擺脫其中之一。
PRIMARY KEY
:
UNIQUE
:
FOREIGN KEY
:
(對於 OP 關於速度的問題,請參閱戈登的評論。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.