在php中获得独特的命中数

时间:2012-01-18 00:09:35

标签: php mysql database counter

我想使用PHP为我的网站添加一个独特的点击计数器。此计数器将为数据库中的每个页面保存访问者的IP。我有这样的数据库结构:

hits有两列:

ip
page_url

我的问题是:在PHP文件中获取访问者的IP后,哪个更好(性能)?

  1. 检查IP地址是否已存在于数据库中。如果还没有在数据库中添加它
  2. 只需添加所有访问者IP(无需重复检查),然后为相关页面获取不同的IP以获得唯一的点击数?

5 个答案:

答案 0 :(得分:6)

如果你使用MySQL,你可能想滥用PRIMARY KEY和ON DUPLICATE KEY UPDATE的组合:

CREATE TABLE hits (
ip VARCHAR(15),
page_url VARCHAR(200),
PRIMARY KEY (ip,page_url),
hitcount INT NOT NULL DEFAULT 0
)

现在点击页面即可

INSERT INTO hits(ip, page_url,hitcount) VALUES('$ip','$url',1)
ON DUPLICATE KEY UPDATE hitcount=hitcount+1

为什么会这样?

  • 另一个唯一的关键是POISON用于写入繁重的表,所以请避免使用它。 真。
  • INSERT ... ON DUPLICATE KEY UPDATE仅锁定行

您可能还想记录上次访问的时间戳:

ALTER TABLE hits ADD COLUMN lastseen TIMESTAMP();

答案 1 :(得分:2)

假设您对简单编程感到满意。

不是真正的“实时”,但几乎是实时 强烈建议您使用自己的格式写入日志文本文件(如果您对Apache的[customlog][1]功能不满意)。

然后,每5分钟设置一个cronjob,如果你想要接近“live”,甚至每1分钟设置一次cronjob,将文本导入到LOAD DATA INFILE的大口中的MySql临时表中,然后更新你的基于GROUP BY ip的visitcounts表。

完全实时 这可能会严重拖累您的服务器,但鉴于您拥有轻量级流量,只需在MySQL中创建两个表。一个只记录正在读取的文章/页面ID + IP +时间(日志表)。另一个包含文章/页面ID和访问计数 - 其中计数更新在第一个表中的GROUP BY ip。

答案 2 :(得分:2)

Eugen Rieck的帮助下,我用时间和日期存储创建了代码。

在此代码中,它存储用户ip,计数,日期和时间。



$ipaddress = '';
    if (getenv('HTTP_CLIENT_IP'))
        $ipaddress = getenv('HTTP_CLIENT_IP');
    else if(getenv('HTTP_X_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
    else if(getenv('HTTP_X_FORWARDED'))
        $ipaddress = getenv('HTTP_X_FORWARDED');
    else if(getenv('HTTP_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_FORWARDED_FOR');
    else if(getenv('HTTP_FORWARDED'))
        $ipaddress = getenv('HTTP_FORWARDED');
    else if(getenv('REMOTE_ADDR'))
        $ipaddress = getenv('REMOTE_ADDR');
    else
$ipaddress = 'UNKNOWN'; // final ip address
$time=date("Y/m/d H:i:s"); // date and time in a single variable
$sql = "INSERT IGNORE INTO `ipaddress` (`id`, `ipaddress`, `count`, `time`) VALUES ('', '$ipaddress','1', '$time') ON DUPLICATE KEY UPDATE count=count+1, time='".$time."'"; // adding ip,count, date and time to table
if($conn->query($sql) === false) {
  trigger_error('Wrong SQL: ' . $sql . ' Error: ' . $conn->error, E_USER_ERROR);
} else {

  $last_inserted_id = $conn->insert_id;
  $affected_rows = $conn->affected_rows;
}

$conn->close();




答案 3 :(得分:1)

我会在(ippage_url)上使用唯一键,可选date。如果记录不存在则会创建,否则会导致错误(但您可以轻松检查错误代码),或者您可以在IGNORE语句中使用INSERT

它只需要一个数据库请求,可能是最快的。您还可以自动保证所有记录都是唯一的,您不需要使用交易。

答案 4 :(得分:0)

嗨,约翰和其他流程偷看......我是编程和MYSQL的新手,...但是我绕过它的方式如下:

我使用一些PHP代码来查询命中数据库,然后评估两列ippage_url,如果它们评估为true则不执行任何操作,否则 ...插入/执行Eugene Rick上面显示的代码......

$ip = $_SERVER['REMOTE_ADDR']; // Get IP Address.

$purl = htmlspecialchars($_GET['page_url']); // Get Page URL.

$results = $mysqli->query("select * from hits"); // Query hits table.

$row = $results->fetch_assoc(); // Fetch array and assign to $row, then evaluate with if statement.

if ($row['ip'] == $ip && $row['page_url'] == $purl) {

} else {
    $mysqli->query("insert into hits (ip,page_url,counter) values ('$ip','$purl',1) on duplicate key update counter=counter+1");
}

我会说实话,我没有在多个IP地址上检查过这个,只是我的。

然而,它为每个基于唯一ip(我正在使用的那个)插入的URL添加了hits表的行,并且当刷新页面时不会增加任何插入的URL的命中数,所以我认为它有效...