PHP,MySQL:是否可以缓存子查询?

时间:2014-10-21 12:07:03

标签: php mysql

我正在寻找一个页面点击计数器。页面的所有者将在页面上放置一个小的计数器图像,其中包含指向Web服务器中脚本的链接;当有人在他们的浏览器中打开页面时,我的脚本将被调用并生成一个命中号码的图像以便发送回浏览器。

$ _ SERVER ['HTTP_REFERER'] 我获取页面网址以识别网页ID: $ page_id ,以及 $ _ SERVER [' REMOTE_ADDR'] - 查看者主机的IP: $ ip ,因为我只计算唯一的IP。这些数据收集在表 Hits(page_id,ip)

为了统计之前的点击次数,我计算了给定页面存储的IP数量:

$res1 = mysqli_query($DB, "SELECT ip FROM Hits WHERE page_id='$page_id'");
$number_of_hits = mysqli_num_rows($res1);

现在我需要测试新到的IP是否没有列在旧的IP中,否则我会丢弃它并且不会增加计数器。我可以在查询已找到的行中运行循环,也可以发出另一个查询:

$res2 = mysqli_query($DB, "SELECT ip FROM Hits WHERE page_id='$page_id' AND ip='$ip'");
$number_of_new_hit_occasions = mysqli_num_rows($res2);
if($number_of_new_hit_occasions == 0) ++$number_of_hits;

但第二个查询基本上是冗余的,并且与第一个查询一样耗费资源;搜索第一个查询中获得的小结果比通过第二个查询中的整个表格搜索效率更高。

我希望我可以将第一个查询存储在名为 IPs_for_given_page 的内存中的虚拟表中(可能以某种方式在 $ res1 中引用),并减少第二个查询查询

$res2 = mysqli_query($DB, "SELECT ip FROM IPs_for_given_page WHERE ip='$ip'");
$number_of_new_hit_occasions = mysqli_num_rows($res2);

有可能吗?

1 个答案:

答案 0 :(得分:1)

如你所述,没有办法缓存结果。但是有一种更有效的方法可以做你正在尝试做的事情。

要计算行数,请使用此类查询并检索单行结果集。这比计算结果集中的行要快得多。

SELECT COUNT(*) FROM Hits WHERE page_id=<<whatever>>

您可以通过以下两项操作来自动执行ip号码的重复数据删除:

首先,在(page_id,ip)上创建一个复合唯一索引。

其次,使用此SQL语句插入命中行。

INSERT IGNORE INTO Hits (page_id, ip) VALUES (<<whatever>>, <<whatever>>) 

唯一索引与IGNORE子句结合在一起可防止MySQL接受同一IP地址的重复命中行。

对于它的价值,我建议的复合索引也会加快您的COUNT查询速度。