聚集索引或分区表?

时间:2012-12-13 02:37:13

标签: mysql sql

我有一个文件共享网站,我的用户对其文件的点击感兴趣。每次点击都会在点击表中存储为新行。

通常,他们想知道他们在特定日期范围内获得的点击次数:

$statement = $db->prepare("SELECT COUNT(DISTINCT ip) FROM clicks WHERE user_id=? AND time BETWEEN ? AND ?");
$statement->execute(array($user_id, $from_date, $to_date));

此外,他们还可以查看特定文件的点击次数:

$statement = $db->prepare("SELECT COUNT(DISTINCT ip) FROM clicks WHERE file_id=? AND time BETWEEN ? AND ?");
$statement->execute(array($file_id, $from_date, $to_date));

这些查询的问题是user_id和file_id不是此表的键(它们不是唯一的)。相反,一个简单的“id”列是主键,但它从不会参与任何查询。

我一直在研究聚簇索引,但在这种情况下我无法弄清楚如何实现它。

随着点击表变得越来越大(5-6百万行),这些查询需要更长的时间(我计划让这个表变得更大)。我读到分区可能就是我需要做的事情?

我是否需要制作群集密钥,对表格进行分区,或两者兼而有之?

供参考,clicks结构:

id time user_id ip file_id

1 个答案:

答案 0 :(得分:3)

您无需更改聚集索引。

我建议创建这些索引:

ALTER TABLE clicks ADD INDEX (file_id, time, ip),
                   ADD INDEX (user_id, time, ip);

通过在索引定义中包含ip,每个查询都应该能够从索引结构本身获取所需的所有信息。这称为覆盖索引。然后查询根本不需要触摸表,因此哪些列构成表的聚簇索引无关紧要。

如果您使用EXPLAIN来分析查询,您应该在Extra字段中看到“Using index”,这表明查询正在获得覆盖索引的好处。

我不认为分区在这种情况下会有所帮助,因为MySQL分区要求分区列必须成为表的任何主键/唯一键的一部分。