【问题标题】:PHP Mysql tracking visitors scalabilityPHP Mysql 跟踪访问者可扩展性
【发布时间】:2012-05-18 02:53:24
【问题描述】:

我有一个从一个代码库运行多个网站的 Web 应用程序。我使用包含在应用程序上运行的站点和域的表来设置它。该应用程序会跟踪访问者,以便我们了解每个站点以及该应用程序在全球范围内获得了多少流量。

我遇到的问题是访问者跟踪非常慢,因为那里有 250 万条记录。运行查询以获取本月的访问者数量需要花费数分钟,这使得我们的数据无法访问。

系统直接从包含所有其他文件的基本 php 文件记录跟踪。当它没有找到现有的识别 cookie 时,它​​会在访问者表中创建一条记录。当它创建记录时,它会为用户分配一个 cookie,这样当他们回来时,他们只创建单个访问者记录。该访问者记录存储了他们查看了多少页以及他们进入了哪个页面(入口页面)以及他们查看的最后一页(退出页面)。

我们获得了相当多的流量,我想通过加快结果的速度来提供每月访问者的报告。

我之前尝试过为 site_id 和日期添加索引,但它似乎对加快速度没有多大帮助...

我们决定自己跟踪分析,而不是使用像谷歌分析这样的工具,这样我们以后就可以用它创建一些更有意义的数据。例如,当正在查看网站的用户提交联系表单并成为 CRM 中的联系人时,我们希望查看该联系人的历史记录,以了解他们在寻求支持之前查看了哪些页面等。

有什么建议吗?表架构如下。提前非常感谢,我一直在努力寻找解决方案。

CREATE TABLE `analytics_track_visits` (
    `id` bigint unsigned NOT NULL AUTO_INCREMENT
    ,`site_id` int(4) unsigned default NULL

    ,`inc` bigint unsigned default NULL
    ,`referer` text NOT NULL
    ,`refer_host` text NOT NULL
    ,`user_agent` text NOT NULL
    ,`browser` text NOT NULL
    ,`os` text NOT NULL
    ,`search_term` text NOT NULL

    ,`entry_page` int(4) unsigned default NULL
    ,`entry_page_url` text default NULL
    ,`exit_page` int(4) unsigned default NULL
    ,`exit_page_url` text default NULL

    ,`created` datetime NOT NULL
    ,`created_ip` varchar(200) NOT NULL default ''
    ,`created_user_id` int(4) unsigned default NULL
    ,`modified` datetime NOT NULL default '0000-00-00'
    ,`modified_user_id` int(4) unsigned default NULL

    ,PRIMARY KEY(`id`)
    ,CONSTRAINT `analytics_track_visits__site` FOREIGN KEY (`site_id`) 
        REFERENCES `site` (`id`) ON DELETE CASCADE
    ,CONSTRAINT `analytics_track_visits__entry_page` FOREIGN KEY (`entry_page`) 
        REFERENCES `page` (`id`) ON DELETE CASCADE
    ,CONSTRAINT `analytics_track_visits__exit_page` FOREIGN KEY (`exit_page`) 
        REFERENCES `page` (`id`) ON DELETE CASCADE
) ENGINE=INNODB;

inc 存储该特定访问者查看的页面数。 entry_page 是我们的 cms 页表的外键(与 exit_page 相同)。 browseros 保存从 user_agent 解释的值。 search_term 存储用于查找入口页面的任何关键字。 site_id 与包含具有域名名称的站点设置列表的表相关。

我怀疑部分问题在于该表从未真正中断过,因此当我们运行报告时,会同时插入和更新该表的活动查询。

【问题讨论】:

  • 您可以通过分析您的 Web 服务器的日志文件来获取所有这些数据......为什么要添加所有这些开销?
  • 甚至比日志文件更好,使用谷歌分析。它有一个 API,因此您可以构建您可能需要的任何自定义报告。
  • 数据比我们想从记录中得到的要深入得多。 Web 应用程序本身有很多不同的功能领域,最终我们想做一些事情,例如:用户点击实时聊天,然后我们可以立即显示用户的最后 20 个页面和操作。或跟踪以查看特定 CRM 联系人在网站上的查看位置。从分析服务器日志中很难发现产品、页面 ID、聊天会话等关系数据。我已经考虑过一般网站统计数据。

标签: php mysql scalability analytics


【解决方案1】:

250 万条记录并不是一张那么大的表。我有一个超过 2500 万条记录的日志表(记录操作、登录、注销、价格变化等)。

如果您通过site_idcreated(只是日期部分)进行查询,我建议创建一个日期类型为 created_date 的索引和一个类似:INDEX (idx_lookup (site_id, created_date) 这样的索引,我相信这应该会为您提供最好的索引。

【讨论】:

  • 是的,250 万并不多,客户希望看到分析屏幕在不超过 5 秒内加载,目前它大约在一两分钟内加载。我认为必须有一种更好的方法来让它更快地加载,或者我可能会被扔硬件所困。我会稍微研究一下索引,看看是否有帮助。
  • 如果索引没有帮助,更好的硬件可能是唯一的选择。从更多内存开始。
【解决方案2】:

在不知道您正在运行哪种查询的情况下,您可能需要考虑以下几点:

  • 为每个站点创建一个单独的表;我知道这似乎不是一个很好的解决方案,但它消除了对表中另一个昂贵索引的需求。
  • 设置一个只读从站来执行您的报告查询;这可以减轻您的主数据库的压力。
  • 我相信 InnoDB 也会为您的所有外键创建索引;这对表格的大小没有帮助(它也会减慢插入速度)。除非您定期删除网页,否则您可以不用这些网页。

如果我能想到更多,我会添加更多提示。

【讨论】:

  • 谢谢,我正在运行报告查询,例如 select count(*) as row_count from analytics_track_visits where site_id = 10 and created between '2012-01-01 00:00:00' and '2012- 01-30 00:00:00'
  • @Mike 你会说你的查询都会有site_id 和一个日期范围吗?如果是这样,您可以在site_idcreated 上引入一个复合索引来使用范围查询。我只是不确定创建索引的顺序:)
  • 感谢您的提示,我会说 90% 的报告查询将包含 site_id 和日期范围。有些不会有 site_id,因为我们会做一些全球报告,但大多数都会有一个日期范围,因为查看任何日期的所有访问者都不会太有用,除非我们正在寻找一个所有时间的数字。我想我将不得不尝试一些不同的索引组合,看看哪种效果最好,到目前为止还没有什么成果
  • @Mike 你可以使用EXPLAIN 语法来更好地理解为什么你的查询很慢。
  • 我考虑过用不同的表或数据库将站点分开,但我也想吃蛋糕,也想吃掉它......因为能够查询整个集合并进行聚合整个应用程序的访问者数据。此外,其他系统可能会使用这些数据并希望向访问者查询 CRM 联系人,因此拥有不同的表会为这些区域引入额外的逻辑,以便在通过联系人查询访问者之前首先决定使用哪个表
猜你喜欢
  • 1970-01-01
  • 2012-06-10
  • 2011-05-30
  • 1970-01-01
  • 2011-04-11
  • 1970-01-01
  • 2012-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多