Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用超过2000万条记录优化mysql查询_Mysql_Sql_Indexing - Fatal编程技术网

如何使用超过2000万条记录优化mysql查询

如何使用超过2000万条记录优化mysql查询,mysql,sql,indexing,Mysql,Sql,Indexing,我在项目中使用MySQL,在mixpanel_数据表中有超过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_da

我在项目中使用MySQL,在mixpanel_数据表中有超过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 column上添加索引器。但是查询需要花费的时间超过15-16秒

有人能帮我优化查询吗?

此索引对sb\U用户可能有帮助:INDEXusername、name、id

从UNION切换到UNION ALL应该可以加快查询速度。但这可能会导致重复的行

您正在获取一年的数据;那占桌子的百分比是多少?如果这是一个很大的百分比,那么没有关于mixpanel_数据的索引是有用的

除非您有UNIQUEbook_名称、电子邮件和语言,否则“分组方式”可能不合适。例如,如果用户从两个不同的ip_地址查看同一本书,该怎么办;查询将传递哪个ip_地址

假设选择之间的唯一差异是

      and  ma.`action` NOT IN('PlayAudio','PauseAudio')
      AND  ma.`spread_id` !=''
如果您使用的是MySQL 8.0,请考虑以下事项:

WITH cte AS
        SELECT ...
            FROM  `mixpanel_data` AS ma
            LEFT JOIN  `sb_users` AS su
               ON ma.`first_name` = su.`username`
            WHERE  ma.`email` !=''
              AND  ma.`created_at` >= '2019-03-24'
              AND  ma.`created_at`  < '2019-03-24' + INTERVAL 1 YEAR
SELECT * FROM cte
      WHERE `action` IN('PauseAudio')
UNION ALL
SELECT * FROM cte
      WHERE `action` NOT IN('PlayAudio','PauseAudio')
        AND `spread_id` !=''
GROUP BY  `email`, `book_name` , `language`
这样做的好处是,它不会在整个工作过程中拖拉sb_用户数据。相反,它是在通过GROUPBY减少行数后从sb_用户获取的

可能会有更多的提示;请完成上面的一些操作,然后提供解释选择和一些表格大小

这是第一个问题。第二个查询在两个方面有所不同:

缺少对扩展id的测试 联合的重复数据消除可能会导致一组不同的行。 虽然没有工会,但我关于在完成分组后加入sb_用户的建议也适用于这里

调试

选择从mixpanel_数据,不包含总和、计数和分组依据,但添加限制。看看数据是否与您期望的一样。 添加总和、计数和分组依据;仔细观察这些结果。 然后连接到另一个表。
你说它违背了要求是什么意思。?然后只发送部分结果?听起来不对。你的查询无效。您可以通过电子邮件、书名、语言进行分组,但可以选择浏览器版本作为示例。组的哪个浏览器版本?最伟大的?最小的?事件的日期、类型、区域等也是如此。由于您似乎正在努力解决聚合组的概念,我建议您将sql模式设置为“仅完整组”;以帮助您构建有效的查询。如果没有该设置,MySQL将通过返回任意值来规避查询的缺陷,这通常意味着不需要的结果。如果您希望每个组的浏览器版本、类型等相同,那么您的数据模型甚至会出现问题,应该在编写任何查询之前对其进行规范化。
WITH cte AS
        SELECT ...
            FROM  `mixpanel_data` AS ma
            LEFT JOIN  `sb_users` AS su
               ON ma.`first_name` = su.`username`
            WHERE  ma.`email` !=''
              AND  ma.`created_at` >= '2019-03-24'
              AND  ma.`created_at`  < '2019-03-24' + INTERVAL 1 YEAR
SELECT * FROM cte
      WHERE `action` IN('PauseAudio')
UNION ALL
SELECT * FROM cte
      WHERE `action` NOT IN('PlayAudio','PauseAudio')
        AND `spread_id` !=''
GROUP BY  `email`, `book_name` , `language`
 SELECT ...
     FROM ( SELECT ...
               FROM mixpanel_data
               -- (no JOIN)
               WHERE ...
               GROUP BY ...
            UNION ALL
               FROM mixpanel_data
               -- (no JOIN)
               WHERE ... (the other)
               GROUP BY ...
          )
    LEFT JOIN sb_users ON ...