下面的查詢將進行全表掃描,但不知道哪里有問題。
詢問:
select journey_level,
src_screen_name from_entity_name,
src_screen_id from_entity_id,
dest_screen_name to_entity_name,
dest_screen_id to_entity_id,
dest_screen_id to_entity_id_list,
concat(journey_level, '-', src_screen_id, '-', src_screen_name) from_entity,
concat(journey_level 1, '-', dest_screen_id, '-', dest_screen_name) to_entity,
count(1) cnt,
sum(ifnull(is_crash, 0)) crash_cnt,
sum(ifnull(is_anr, 0)) anr_cnt,
sum(ifnull(is_rage, 0)) rage_cnt,
case dest_screen_id
when -1
then 'Red'
else ''
end node_color
from ue_summary.user_journey_screens_1943 s
where first_session_created_at between '2022-09-17 00:00:00' and '2022-10-17 10:42:35'
and s.platform = '1'
and journey_level <= '4'
group by journey_level,
from_entity_id,
from_entity_name,
to_entity_id,
to_entity_name;
解釋計劃;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: s
partitions: NULL
type: ALL
possible_keys: date_platform_level
key: NULL
key_len: NULL
ref: NULL
rows: 799471542
filtered: 1.67
Extra: Using where; Using temporary
表結構;
*************************** 1. row ***************************
Table: user_journey_screens_1943
Create Table: CREATE TABLE `user_journey_screens_1943` (
`id` bigint NOT NULL AUTO_INCREMENT,
`app_id` int DEFAULT NULL,
`platform` tinyint DEFAULT NULL,
`asi` bigint DEFAULT NULL,
`first_session_created_at` datetime DEFAULT NULL,
`user_task_id` bigint DEFAULT NULL,
`app_version_id` int DEFAULT NULL,
`journey_level` int DEFAULT NULL,
`src_screen_id` bigint DEFAULT NULL,
`src_screen_name` varchar(300) DEFAULT NULL,
`src_capture_time` bigint DEFAULT NULL,
`src_capture_time_relative` bigint DEFAULT NULL,
`dest_screen_id` bigint DEFAULT NULL,
`dest_screen_name` varchar(300) DEFAULT NULL,
`dest_capture_time` bigint DEFAULT NULL,
`dest_capture_time_relative` bigint DEFAULT NULL,
`is_crash` tinyint DEFAULT NULL,
`is_anr` tinyint DEFAULT NULL,
`is_rage` tinyint DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `app_id_date_level` (`app_id`,`first_session_created_at`,`journey_level`),
KEY `asi` (`asi`),
KEY `date_platform_level` (`first_session_created_at`,`platform`,`journey_level`)
) ENGINE=InnoDB AUTO_INCREMENT=1937612717 DEFAULT CHARSET=latin1
我錯過了任何索引還是由于其他任何原因?
uj5u.com熱心網友回復:
您的查詢的 WHERE 子句包含兩個值范圍過濾器,一個在DATETIME列上,另一個在具有明顯較小值的 INT 上。這是對 TINYINT 上的一個相等過濾器的補充。
MySQL 的索引是 BTREE 索引。您可以將它們視為按順序排序的查找表。因此,要讓查詢有效地使用索引,索引應該以匹配相等的列開始,然后僅以范圍匹配的一列結束。我猜您的 DATETIME 列比您的 TINYINT 列更具選擇性,所以我猜索引應該包含該列。
因此,如果您在其上放置索引(platform, first_session_created_at)將有助于您的查詢。為什么?
MySQL 可以隨機訪問第一個符合條件的行的索引。在您的情況下,它是第一行,platform=1日期 >= 您的日期范圍的開始。
然后,它可以進行索引范圍掃描:它可以順序掃描索引,直到它到達最后一個符合條件的行。相反,您的計劃顯示它正在掃描整個表以獲取結果,因為它認為這將花費更少的時間來掃描從 DATETIME 列開始的索引。一般來說,索引范圍掃描比全表掃描快得多。所以,你想要這個:
CREATE INDEX platform_date ON tbl (platform, first_session_created_at);
這里還有一個可能的改進:您正在對多個列執行 GROUP BY。如果您以與 GROUP BY 相同的順序將這些列包含在索引中,MySQL 可能能夠從索引順序執行分組操作,而不必構建內部臨時表。這可能會也可能不會。如果是,using temporary則不會出現在您的 EXPLAIN 中。嘗試將列添加到索引中,如下所示:
CREATE INDEX platform_date ON tbl (platform,
first_session_created_at,
journey_level,
from_entity_id,
from_entity_name,
to_entity_id,
to_entity_nam );
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/516991.html
