MYSQL查询优化(需要提高速度)

时间:2011-06-10 01:05:32

标签: mysql query-optimization

我有一个包含Google Analytics数据的MySQL表:

CREATE TABLE IF NOT EXISTS `analytics_data` (
  `ga_profile_id` int(11) NOT NULL,
  `page` varchar(200) NOT NULL,
  `source` varchar(150) NOT NULL,
  `medium` varchar(50) NOT NULL,
  `keyword` varchar(200) NOT NULL,
  `bounces` int(11) NOT NULL,
  `entrances` int(11) NOT NULL,
  `exits` int(11) NOT NULL,
  `new_visits` int(11) NOT NULL,
  `page_views` int(11) NOT NULL,
  `unique_page_views` int(11) NOT NULL,
  `time_on_page` int(11) NOT NULL,
  `visits` int(11) NOT NULL,
  `date` date NOT NULL,
  KEY `ga_profile_id` (`ga_profile_id`,`source`,`medium`,`date`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

我有一个查询来计算在给定时间段内基于Google Analytics(分析)个人资料ID(ga_profile_id)的访问者总数:

SELECT 
    SUM( `visits` ), ( UNIX_TIMESTAMP( `date` ) - 21600 ) * 1000 AS date 
FROM `analytics_data` 
WHERE 
    `date` >= '2011-05-09' AND `date` <= '2011-06-08' AND `ga_profile_id` = [...]
GROUP BY `date`

我们有大约450万条记录。

索引数据:

Type: BTREE
Fields/Cardinality:
ga_profile_id / 100
source / 10196
medium / 10196
date / 149893

EXPLAIN SELECT
- id :1
- select_type :SIMPLE
- 表格:analytics_data
- 输入:参考
- possible_keys :ga_profile_id
- :ga_profile_id
- 参考:const
- :219555
- 额外:使用where;使用临时;使用filesort

平均执行时间: 1秒

我们在虚拟专用服务器上,大多数查询都在.0003 - 0.03秒内执行。 LONG查询(我将在某些时候进行优化)通常为.3秒。

我试过调整键,忽略了一些键,改变了一些值,似乎没有任何东西以积极的方式影响它。考虑到这是页面上许多查询中的一个。

我正在考虑将MyISAM改为记忆 - 欢迎任何想法。

5 个答案:

答案 0 :(得分:4)

您需要按此特定顺序创建复合索引ga_profile_id + date。并且你将获得这种查询所能获得的最佳效果。

进一步可能的优化是预先计算每个日期的访问量并将其用于快速计算。

答案 1 :(得分:1)

  

我有一个查询来根据给定时间段内的Google Analytics(分析)个人资料ID(ga_profile_id)计算访问者总数

它似乎已经非常优化了...在您撰写此答案时的问题中,您已经删除了查询中最有趣的部分(ga_profile_id上的实际条款),这是最多的尽可能选择性 - 因此当前的指数使用。

最好的情况是,如果将其放在多列索引中,您可以设法利用date上的索引,例如(date, ga_profile_id) 或其他方式,具体取决于您的使用模式和表统计信息。

请参阅indexes dos and donts

答案 2 :(得分:1)

运行索引将是第一个也是最简单的选项,但如果这没有帮助,我建议您更多地了解一些基本的数据库管理策略,如表分区。

答案 3 :(得分:0)

@Kerry,看看Denis的解决方案......他提供的唯一替代方案是将指数设置为PROFILE ID FIRST,THEN Date,否则,您的索引将被合并给其他在同一时间段内也有行动的人......

另外,@ Bohemian将分组缩减到第二个是一个强点......您可能希望根据完整日期/时间列结果的DATE ONLY部分进行排序。

答案 4 :(得分:0)

如果您的查询中有典型的日期范围,那么您可以考虑水平分区您的表。也许当大多数数据“过时”并且您只在一个或多个分区上拥有所需的“新”数据而在另一个分区上拥有所有这些旧数据时,它也会有所帮助。 RANGE Partitioning