【问题标题】:Getting unique hit count in php在 php 中获取唯一命中数
【发布时间】:2012-01-18 00:09:34
【问题描述】:

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

hits 有两列:

ip
page_url

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

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

【问题讨论】:

  • 为了性能,最好稍后解析 apache 的访问日志,甚至可能在其他服务器上,让计数有所滞后,而不是试图跟上请求。
  • 我只有一台服务器。而且我网站的流量不是很多。
  • 在这种情况下,只需在(ip,page_url) 上创建一个UNIQUE 索引,然后执行一个INSERT IGNORE ...
  • 嗯,非常感谢。这不会导致错误?
  • 避免在写繁重的表上不必要的索引!请改用主节点。

标签: php mysql database counter


【解决方案1】:

如果您使用的是 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();

【讨论】:

  • 我也喜欢时间戳字段。 (你也可以让它自动更新,或者添加两个时间戳字段:firstseen 和 lastseen)
  • 我的版本正在自动更新:dev.mysql.com/doc/refman/5.1/en/timestamp.html 说“既没有 DEFAULT 也没有 ON UPDATE 子句,它与 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 相同。”
  • 哦不!现在我检查了这段代码。它计入不同的 IP,不计入独特的点击量。我需要计算页面的唯一命中的查询。我的意思是,我需要相关页面的不同 IP 计数
  • 如果表定义正确,这是不可能的:ip 是主键的一部分!发布您的“SHOW CREATE TABLE 点击”
  • 我的点击表和你发的一样。我也有“页面”表。是否可以将“unique_hits”列添加到“pages”表中,然后如果在相关页面的命中表中找不到发布的 IP,则编写更新“unique_hits”的查询?
【解决方案2】:

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

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

然后,每 5 分钟设置一次 cronjob,如果您想接近“实时”,甚至每 1 分钟设置一次,使用 LOAD DATA INFILE 将文本导入 MySql 临时表,然后更新您的访问计数表基于 GROUP BY ip。

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

【讨论】:

    【解决方案3】:

    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();

    【讨论】:

      【解决方案4】:

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

      它只需要向数据库发出一个请求,并且可能是最快的。您还可以自动保证所有记录都是唯一的,并且您不需要使用事务。

      【讨论】:

        【解决方案5】:

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

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

        $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 添加行到命中表中,并且在刷新页面时不会增加任何插入 URL 的命中计数,所以我认为它可以工作...

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-17
          • 2023-03-25
          • 1970-01-01
          • 2014-08-21
          • 2012-05-11
          相关资源
          最近更新 更多