mysql - 使用 INDEXING 优化 SELECT MySql 查询

标签 mysql performance optimization indexing

我正在为一家媒体内容广播公司开发数据分析仪表板。即使用户点击某个 channel ,日志/记录也会存储到 MySQL DB 中。以下是存储有关 channel 播放时间的数据的表格。

这是表结构:

 _____________________________________
|           ID INT(11)                |
 _____________________________________
|        Channel_ID INT(11)           |
 _____________________________________
|       playing_date (DATE)           |
 _____________________________________  
|      country_code VARCHAR(50)       | 
 _____________________________________
|      playtime_in_sec INT(11)        | 
 _____________________________________
| count_more_then_30_min_play INT(11) | 
 _____________________________________
|    count_15_30_min_play INT(11)     | 
 _____________________________________
|       count_0_15_min_play           | 
 _____________________________________
|   channel_report_tag VARCHAR(50)    |
 _____________________________________ 
|   device_report_tag VARCHAR(50)     |
 _____________________________________ 
|   genre_report_tag VARCHAR(50)      |
 _____________________________________

我在仪表板图表构建之一后面运行的查询是:

    SELECT 
        channel_report_tag,
        SUM(count_more_then_30_min_play) AS '>30 minutes', 
        SUM(count_15_30_min_play) AS '15-30 Minutes', 
        SUM(count_0_15_min_play) AS '0-15 Minutes'
    FROM 
        channel_play_times_cleaned 
    WHERE 
        playing_date BETWEEN '' AND ''
        AND country_code LIKE ''        
        AND device_report_tag LIKE '' 
        AND channel_report_tag LIKE  ''
    GROUP BY 
        channel_report_tag
    LIMIT 10

这个查询基本上需要花费大量时间来返回结果集(假设表数据每天超过一百万条记录,并且每秒都在增加)。我遇到了这个堆栈溢出问题:What generic techniques can be applied to optimize SQL queries?其中基本上提到了使用索引作为优化 SQL 查询的技术之一。目前我很困惑如何应用索引(即在哪些列上)以优化上述查询。如果有人可以根据我的具体情况提供创建索引的帮助,我将不胜感激。对于像我这样的初学者来说,任何其他专家的意见都是值得欢迎的。

编辑:

根据@Thomas G 的建议,

我尝试改进我的查询并使其更加具体:

SELECT 
        channel_report_tag,
        SUM(count_more_then_30_min_play) AS '>30 minutes', 
        SUM(count_15_30_min_play) AS '15-30 Minutes', 
        SUM(count_0_15_min_play) AS '0-15 Minutes'
    FROM 
        channel_play_times_cleaned 
    WHERE 
        playing_date BETWEEN '' AND ''
        AND country_code = 'US'        
        AND device_report_tag = 'j8' 
        AND channel_report_tag = 'NAT GEO'
    GROUP BY 
        channel_report_tag
    LIMIT 10

最佳答案

我开始在评论中写下这些,因为这些只是提示,而不是明确的答案。但这太长了

首先,对 WHERE 子句中出现的列建立索引是常识(但并不总是经验法则):

   playing_date BETWEEN '' AND ''
    AND country_code LIKE ''        
    AND device_report_tag LIKE '' 
    AND channel_report_tag LIKE  ''

如果您的列具有非常高的基数(您的标签列???),那么为它们建立索引可能不是一个好主意。 Country_codeplaying_date 应建立索引。

这里的问题是您的查询中有太多 LIKE。这个操作符是一个 killer ,你在 3 列上使用它。这对数据库来说太糟糕了。所以问题是:真的需要吗?

例如,我认为没有明显的理由对国家/地区代码进行LIKE。你真的会这样查询吗:

AND country_code LIKE 'U%'

检索英国和美国? 你可能不会。您很可能知道您正在搜索的国家/地区,因此您应该这样做:

AND country_code IN ('UK','US')

如果对国家/地区列建立索引,速度会快很多

接下来,如果您确实想在 2 个标签列上进行 LIKE,而不是进行 LIKE,您可以尝试此操作

AND MATCH(device_report_tag) AGAINST ('anything*' IN BOOLEAN MODE)

还可以将标签列索引为 FULLTEXT,特别是当您使用 LIKE ='anything%' 进行搜索时。如果您使用 LIKE='%anything%' 进行搜索,索引可能不会有太大帮助。

我还可以指出,每天有数百万行,您可能必须对表进行分区(例如在日期上)。根据您的数据,日期的复合索引和其他内容可能会有所帮助。

确实,对于您的复杂问题,没有简单直接的答案,尤其是您所展示的内容(不是很多)。

关于mysql - 使用 INDEXING 优化 SELECT MySql 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39529205/

相关文章:

MySQL-[HY000][1005]无法创建表 'dbc18b3536647.results'(错误号: 150)

mysql - 通用投票表与单独的投票表?

regex - 是否应该一直使用原子组来加速失败?

javascript - jQuery/Javascript 框架效率

PHP 优化 - 减少内存使用

mysql - Codeigniter - database.php 在线服务器的主机名是什么?

php - PDO PHP 使用 UNIX_TIMESTAMP() 准备和执行

MySQL 查询最大/最小字段

c# - 为什么通过 Pointer 转换结构很慢,而 Unsafe.As 很快?

wordpress - Nginx Fastcgi_cache性能——磁盘缓存VS tmpfs缓存VS静态文件