2016-09-16 61 views
2

我正在为媒体内容广播公司开发数据分析仪表板。即使用户点击某个频道,日志/记录也会存储到MySQL DB中。以下是存储关于频道播放时间的数据的表格。使用INDEXING优化SELECT MySql查询

这里是表结构:

_____________________________________ 
|   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 
+0

你要做的列的索引,对于第一变更表结构,就在“应用,恢复”按钮,还有一个标签部分,在那里你必须选择“索引“选项卡,在此选项卡中选择要索引的列,然后应用 –

+0

@chiragpatel”我如何应用索引“。我所问的是在哪些列上应用w.r.t我提到的查询。感谢任何关注的方式。 –

+0

索引适用于位于where条件的列,并且如果该列数据类型为Integer,则执行速度较快。 –

回答

1

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

首先,这是常识(但不总是一个经验法则),以指数出现在WHERE子句中的列:

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

如果你的列有非常高的基数(你的标签栏???),它可能不是一个好主意,他们索引。应编入Country_codeplaying_date

这里的问题是在您的查询中有这么多LIKE。这个操作员是一个杀手,你在3列上使用它。这对数据库来说很不好。所以问题是:这真的需要吗?

比如我看不出有什么明显的原因做出LIKE国家代码。你真的会这样查询:

AND country_code LIKE 'U%' 

要检索英国和美国? 你可能不会。机会是很高,你会知道你正在搜索的国家,所以你应该这样做,而不是:

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

这将是快了很多,如果该国列被编

接下来,如果你真想让LIKE您2标签栏,而不是做一个LIKE特别是如果你有LIKE ='anything%'搜索你可以试试这个

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

也可以索引你的标签栏为FULLTEXT。我用LIKE='%anything%'进行搜索时,索引不会有太大的帮助。

我也可以说每天有数百万行,你可能需要PARTITION你的表(例如日期)。并根据您的数据,日期和其他内容的复合索引可能会有所帮助。

真的,你的复杂问题没有简单直接的答案,特别是你展示的东西(不是很多)。

+0

这些提示但非常有帮助,谢谢。基本上使用LIKE的原因是country_code,device_report_tag和channel_report_tag由用户输入的仪表板参数控制。但是你关于国家代码的观点是真实的,我可以在那里使用IN而不是LIKE。 –

1

独立索引不如复合索引有用。不幸的是,你有很多可能的组合,你(显然)允许通配符,这可能会破坏索引的效用。

建议你用客户端代码来构建WHERE条款,而不是'

填充它在复合索引,把最后一个范围。 date BETWEEN ... AND ...是一个“范围”。

LIKE 'abc' -- same as = 'abc', so why not change to that. 
LIKE 'abc%' -- is a "range" 
LIKE '%abc' -- can't use an index. 
IN ('CA', 'TX') -- sometimes optimizes like '=', sometimes like 'range'. 

因此......观察用户请求的查询,然后构建复合索引以满足它们。一些规则:

  • 最多一个范围,并把它放在最后。
  • 首先放入'='列。
  • INDEX(a,b)INDEX(a,b,c)处理,所以只包括后者。
  • 不要超过十几个索引。

Index Cookbook

+0

如果我使用这个查询,用=运算符替换LIKE。请看看我的问题编辑。 –

+0

为了清楚起见,当你知道这是你想要的时候使用'='。没有通配符'='和'LIKE'的表现非常相似。如果最终用户_can_提供通配符,那么可以简单地使用'LIKE'并让优化器意识到它可以改进它。 –