【发布时间】:2016-04-15 12:58:42
【问题描述】:
我们有一个分析产品。我们为每个客户提供一个 JavaScript 代码,他们将其放在他们的网站中。如果用户访问我们的客户站点,java 脚本代码会访问我们的服务器,以便我们代表该客户存储此页面访问。每个客户都包含唯一的域名。
我们将这个页面访问存储在 MySql 表中。
以下是表架构。
CREATE TABLE `page_visits` (
`domain` varchar(50) DEFAULT NULL,
`guid` varchar(100) DEFAULT NULL,
`sid` varchar(100) DEFAULT NULL,
`url` varchar(2500) DEFAULT NULL,
`ip` varchar(20) DEFAULT NULL,
`is_new` varchar(20) DEFAULT NULL,
`ref` varchar(2500) DEFAULT NULL,
`user_agent` varchar(255) DEFAULT NULL,
`stats_time` datetime DEFAULT NULL,
`country` varchar(50) DEFAULT NULL,
`region` varchar(50) DEFAULT NULL,
`city` varchar(50) DEFAULT NULL,
`city_lat_long` varchar(50) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
KEY `sid_index` (`sid`) USING BTREE,
KEY `domain_index` (`domain`),
KEY `email_index` (`email`),
KEY `stats_time_index` (`stats_time`),
KEY `domain_statstime` (`domain`,`stats_time`),
KEY `domain_email` (`domain`,`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
我们没有此表的主键。
MySql 服务器详情
是谷歌云MySql(版本为5.6),存储容量10TB。
截至目前,我们的表中有 3.5 亿行,表大小为 300 GB。即使一个客户与另一个客户之间没有关系,我们也会将所有客户详细信息存储在同一个表中。
问题 1:对于我们的少数客户在表中具有大量行,因此针对这些客户的查询性能非常慢。
示例查询 1:
SELECT count(DISTINCT sid) AS count,count(sid) AS total FROM page_views WHERE domain = 'aaa' AND stats_time BETWEEN CONVERT_TZ('2015-02-05 00:00:00','+05:30','+00:00') AND CONVERT_TZ('2016-01-01 23:59:59','+05:30','+00:00');
+---------+---------+
| count | total |
+---------+---------+
| 1056546 | 2713729 |
+---------+---------+
1 row in set (13 min 19.71 sec)
我将在此处更新更多查询。我们需要在 5-10 秒内得到结果,这可能吗?
问题 2:表大小正在迅速增加,到今年年底我们可能会达到 5 TB 的表大小,因此我们想要对表进行分片。我们希望将与一位客户相关的所有记录保存在一台机器上。这种分片的最佳做法是什么。
我们正在考虑针对上述问题采取以下方法,请建议我们解决这些问题的最佳做法。
为每个客户创建单独的表
1) 如果我们为每个客户创建单独的表,有什么优点和缺点。截至目前,我们拥有 30k 客户,到今年年底我们可能会达到 100k,这意味着 DB 中有 100k 表。我们同时访问所有表以进行读取和写入。
2) 我们将使用同一张表并根据日期范围创建分区
更新:“客户”是由域决定的吗? 答案是肯定的
谢谢
【问题讨论】:
标签: mysql database query-performance