簡體   English   中英

優化具有數百萬行的大型 SELECT/JOIN 查詢

[英]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
  • 是索引

UNIQUE

  • 將列(或列的組合)聲明為 UNIQUE
  • 是索引

FOREIGN KEY

  • 如果索引不存在,則聲明索引
  • 提供完整性約束,當您插入在另一個表中沒有對應行的行時提醒您
  • 可選地提供“級聯”操作

(對於 OP 關於速度的問題,請參閱戈登的評論。)

暫無
暫無

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

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