2017-02-27 65 views
1

我一直在阅读很多很好的答案,在这个网站上的时间不同的问题,但这是我第一次发布。所以提前感谢您的帮助。mySQL查询优化浏览跟踪器

这里是我的问题:

我有一个MySQL的表跟踪访问不同的网站,我们有。这是表格结构:

create table navigation_base (
      uid int(11) NOT NULL, 
      date datetime not null, 
      dia date not null, 
      ip int(4) unsigned not null default 0, 
      session_id int unsigned not null, 
      cliente smallint unsigned not null default 0, 
      campaign mediumint unsigned not null default 0, 
      trackcookie int unsigned not null, 
      adgroup int unsigned not null default 0, 
      PRIMARY KEY (uid) 
    ) ENGINE=MyISAM; 

此表格有答案。 7000万行(平均每天110,000)。

在我们创建的索引与下面的命令该表:

alter table navigation_base add index dia_cliente_campaign_ip (dia,cliente,campaign,ip); 
alter table navigation_base add index dia_cliente_campaign_ip_session (dia,cliente,campaign,ip,session_id); 
alter table navigation_base add index dia_cliente_campaign_ip_session_trackcookie (dia,cliente,campaign,ip,session_id,trackcookie); 

,我们使用此表来获得由客户,天,活动用下面的查询分组访客统计:

select 
    dia, 
    navigation_base.campaign, 
    navigation_base.cliente, 
    count(distinct ip) as visitas, 
    count(ip) as paginas_vistas, 
    count(distinct session_id) as sesiones, 
    count(distinct trackcookie) as cookies 
from navigation_base where 
    (dia between '2017-01-01' and '2017-01-31') 
    group by dia,cliente,campaign order by NULL 

即使创建了这些索引,一个月的响应时间也相对较慢;在我们的服务器上约3秒钟。

有没有加快这些查询的一些方法?

在此先感谢。

回答

1

有了这么多的数据,单独编制索引可能没有什么帮助,因为数据中有很多相似之处。除了你有GROUP BY和SORT以及聚合。所有这些结合在一起使得优化非常困难。 partitioning是前进的方向,这是因为:

一些查询可以在如下事实大大优化数据 满足给定的WHERE子句只能在一个或多个 分区,其中自动排除任何剩余的分区被存储从 进行搜索。由于在创建分区 表后,可以更改分区,因此可以重新组织数据以增强 频繁查询,这些查询在第一次设置分区方案时可能并不经常使用。

如果这不适合你,它仍然可能

此外,MySQL的5.7支持 查询明确的分区选择。例如,SELECT * FROM t PARTITION(p0,p1)WHERE c 仅选择与WHERE 条件匹配的分区p0和p1中的那些行。

ALTER TABLE navigation_base 
     PARTITION BY RANGE(TO_DAYS(dia)) (
     PARTITION p0 VALUES LESS THAN (TO_DAYS('2018-12-31')), 
     PARTITION p1 VALUES LESS THAN (TO_DAYS('2017-12-31')), 
     PARTITION p2 VALUES LESS THAN (TO_DAYS('2016-12-31')), 
     PARTITION p3 VALUES LESS THAN (TO_DAYS('2015-12-31')), 
     .. 
     PARTITION p10 VALUES LESS THAN MAXVALUE)); 

使用更大或更小的分区,你认为合适。

要记住的最重要的因素是mysql每个表只能使用一个索引。所以明智地选择你的指数。

+0

嗨。谢谢你快速的回复。前段时间尝试分区,但没有帮助。不过我会再试一次。我所做的只是创建一个包含一个月数据的表格,因为这可能与某个分区类似。 Te查询时间在大表和小表中相同。问候。 –

+0

我看到了你试过指标无分区的好处。单独的桌子也不会更好。认为它是这样的:有多少_rows_需要读(包括传入了行),以满足查询。所有三种情况的答案都是一样的。 –

1

如果你只在每天的粒度做COUNT(DISTINCT ...),然后建立和增量保持的汇总表。它将通过几乎相同的SELECT,但只取昨天的数据查询中的每个晚上增强。

然后用这个汇总表进行每月一次的“报告”。

More on Summary Tables

+0

嗨瑞克!呦读我的心......或者我读你;-)试图Ÿ最终选择了像你这样的解决方案不同的方法之后。它就像是一个“动态ETL”,可以更新中间表。此表格包含按天,客户和广告系列的汇总数据。用户每次执行查询时,ETL(在PHP)查找日期不是在数据表中,并生成它们的飞行。感谢大家的帮助。问候 –