之前可能会问过,但无论如何都是这种情况。
我有一个大表(在使用InnoDB的MySQL上),这基本上是一个巨大的日志,没有关系花哨的东西。
3个字段:Customer_ID,TimeStamp,Log_Data(这是一个微小的文本,如“访问过的网页”或“登录”)。
由于我在每天接收大约10,000名用户的网页中记录客户端的活动,因此该表增长得非常快。
在某一特定时刻,我想知道有多少客户在网站上做了什么。
所以我正在运行以下查询'SELECT DISTINCT Customer_ID FROM table;',并且我已经开始注意到随着表变大,查询需要更长时间,这非常好并且完全可以预期。在一个给定时间,查询开始花费超过5分钟完成。
我想找到一种更快的方式,所以我尝试了这个。假设我正在使用一个包含100万行的表。我开始将该表拆分为10个表,每个表100K个记录。然后我运行'SELECT DISTINCT Customer_ID FROM table;'在每张桌子上,以及所有结果我只是'排序| uniq | wc'他们在命令行上并得到相同的结果。
令人惊讶的是,该方法花费的时间不到另一个执行时间的一半。
我自己几乎已经回答了这个问题,10 * 100K表比1 * 1M表快,但也许我做错了,可能更多是性能调优的问题或者因为表应该设计的东西无论大小如何,表现都很好。
让我知道你的想法。
感谢阅读。
更新:这是我创建表格的方式:
CREATE TABLE `mydb`.`mytable` (
`Customer_ID` BIGINT( 20 ) UNSIGNED NOT NULL,
`unix_time` INT( 10 ) UNSIGNED NOT NULL,
`data` TINYTEXT NOT NULL,
KEY `fb_uid` ( `fb_uid` )
) ENGINE = INNODB DEFAULT CHARSET = utf8;
答案 0 :(得分:2)
虽然您的100K * 10解决方案确实使查询更快,但听起来很难维护,可能不是最好的方法。
“桌子应该设计成无论大小都能很好地运行”
当表格对于您正在使用的数据库引擎而言太大时,您必须意识到这是不可能的。
那你能做什么?解决方案可能涉及您对此数据运行的查询类型。
这里的一条经验法则是不存储您不需要的数据。另一种方法是以易于查询的方式存储数据 - 即使您确实需要1M行原始数据,您仍然可以将一些聚合数据(或元数据)存储在另一个表中,例如:每天唯一customer_id的表格,在一天结束时计算。
答案 1 :(得分:2)
您需要一个以 Customer_ID开头的索引,以使您的查询更快。如果您有一个只包含它的索引,那么它将无法以最佳方式使用它。以下是创建它的方法:
CREATE INDEX idx_cid ON table (Customer_ID)
同样,您可以直接从数据库获取计数:
SELECT COUNT(DISTINCT(Customer_ID)) FROM table
如果您想将其缩小到一段时间,那么您需要一个复合索引:
CREATE INDEX idx_ts_cid ON table (TimeStamp, Customer_ID)
然后上个月的查询会是这样的:
SELECT COUNT(DISTINCT(Customer_ID)) FROM table
WHERE TimeStamp BETWEEN "2011-03-01" AND "2011-04-01"
答案 2 :(得分:1)
要添加到其他人,因为您说您没有做任何“花哨的关系事物”,您可能还想考虑使用面向大量数据集(和简单表)的数据库解决方案。 MongoDB就是一个例子。
我应该补充说,只有当数据库模式的其余部分也非常大且非关系时,这才有意义:)
答案 3 :(得分:0)
似乎你没有user_id字段的索引,或者一个用户有很多行说400万行中的一百万。