【发布时间】:2020-03-25 05:06:26
【问题描述】:
我的项目使用 MySQL,并且在“mixpanel_data”表中有超过 2000 万条记录。
因此,当我尝试获取过去 6 个月的记录时,它会中断请求。它只为我提供了最近 5-10 天的记录
我正在使用以下 MySQL 查询。
SELECT `sb_users`.`id`,`sb_users`.`name`, SUM(`mixpanel_data`.duration) as timeCount,
COUNT(`mixpanel_data`.spread_id) as PageCount,`mixpanel_data`.`language`,
`mixpanel_data`.`created_at`, `mixpanel_data`.`book_name`,
`mixpanel_data`.`email`, `mixpanel_data`.`ip_address`,
`mixpanel_data`.`event_date`, `mixpanel_data`.`type`,
'Read', `mixpanel_data`.`unique_session_id`, `mixpanel_data`.`operating_system`,
`mixpanel_data`.`country`, `mixpanel_data`.`region`, `mixpanel_data`.`city`,
`mixpanel_data`.`device`, `mixpanel_data`.`browser`,
`mixpanel_data`.`browser_version`
FROM `mixpanel_data`
LEFT JOIN `sb_users` ON `mixpanel_data`.`first_name` = `sb_users`.`username`
WHERE `mixpanel_data`.`email` !=''
AND `mixpanel_data`.`created_at` Between '2019-03-24' AND '2020-03-24'
and `mixpanel_data`.`action` IN('PauseAudio')
GROUP BY `mixpanel_data`.`email`, `mixpanel_data`.`book_name` ,
`mixpanel_data`.`language`
UNION
SELECT `sb_users`.`id`,`sb_users`.`name`, SUM(`mixpanel_data`.duration) as timeCount,
COUNT(`mixpanel_data`.spread_id) as PageCount,`mixpanel_data`.`language`,
`mixpanel_data`.`created_at`, `mixpanel_data`.`book_name`,
`mixpanel_data`.`email`, `mixpanel_data`.`ip_address`,
`mixpanel_data`.`event_date`, `mixpanel_data`.`type`,
'Read', `mixpanel_data`.`unique_session_id`, `mixpanel_data`.`operating_system`,
`mixpanel_data`.`country`, `mixpanel_data`.`region`, `mixpanel_data`.`city`,
`mixpanel_data`.`device`, `mixpanel_data`.`browser`,
`mixpanel_data`.`browser_version`
FROM `mixpanel_data`
LEFT JOIN `sb_users` ON `mixpanel_data`.`first_name` = `sb_users`.`username`
WHERE `mixpanel_data`.`email` !=''
AND `mixpanel_data`.`created_at` Between '2019-03-24' AND '2020-03-24'
and `mixpanel_data`.`action` NOT IN('PlayAudio','PauseAudio')
AND `mixpanel_data`.`spread_id` !=''
GROUP BY `mixpanel_data`.`email`, `mixpanel_data`.`book_name` ,
`mixpanel_data`.`language`
我尝试使用以下查询更改我的查询,但它不适合我。它还破坏了请求,并且给我的记录也更少。
SELECT sb_users.id,
sb_users.NAME,
Count(mixpanel_data.spread_id) AS PageCount,
SUM(CASE When action IN ('PauseAudio') Then duration Else 0 End) as total, SUM(CASE When action NOT IN ('PlayAudio', 'PauseAudio') Then duration Else 0 End) as Sectotal,
mixpanel_data.language,
mixpanel_data.created_at,
mixpanel_data.book_name,
mixpanel_data.email,
mixpanel_data.ip_address,
mixpanel_data.event_date,
mixpanel_data.type,
'Read',
mixpanel_data.unique_session_id,
mixpanel_data.operating_system,
mixpanel_data.country,
mixpanel_data.region,
mixpanel_data.city,
mixpanel_data.device,
mixpanel_data.browser,
mixpanel_data.browser_version
FROM `mixpanel_data`
LEFT JOIN sb_users
ON `mixpanel_data`.`first_name` = `sb_users`. `username`
WHERE
mixpanel_data.email != '' AND mixpanel_data.`created_at` Between '2019-03-24' AND '2020-03-24'
AND `mixpanel_data`.`spread_id` !='' GROUP BY mixpanel_data.email,
mixpanel_data.book_name,
mixpanel_data.language
我还尝试在 first_name、username 和 created_at 列上添加索引器。但是查询需要很多时间(超过 15-16 秒)
谁能帮我优化查询?
【问题讨论】:
-
“它破坏了请求。” 是什么意思?然后只发送一部分结果?这听起来不对。
-
您的查询无效。您按
email, book_name, language分组,但例如选择browser_version。组的哪个浏览器版本?最伟大的?最小的?event_date、type、region等也是如此。由于您似乎对聚合组的概念感到困惑,我建议您使用SET sql_mode = 'ONLY_FULL_GROUP_BY';来帮助您构建有效的查询。 (如果没有该设置,MySQL 通过返回任意值来规避查询的缺陷,这通常意味着不希望的结果。) -
如果您希望每个组的浏览器版本、类型等都相同,那么您的数据模型甚至存在问题,应该在编写任何查询之前对其进行规范化。