1

我目前正在尝试为使命召唤 4 创建一个日志解析器。解析器本身位于 php 中,并读取特定服务器的日志文件的每一行,并使用 mysqli 将所有统计信息写入数据库。数据库已经到位,我相当肯定(以我有限的经验)它们组织良好。但是,我不确定应该以何种方式将更新/插入查询发送到数据库,或者更确切地说,哪种方式是最佳的。

我的数据库结构如下

-- --------------------------------------------------------

-- 
-- Table structure for table `servers`
-- 

CREATE TABLE IF NOT EXISTS `servers` (
`server_id` tinyint(3) unsigned NOT NULL auto_increment,
`servernr` smallint(1) unsigned NOT NULL default '0',
`name` varchar(30) NOT NULL default '',
`gametype` varchar(8) NOT NULL default '',
PRIMARY KEY (`server_id`),
UNIQUE KEY (`servernr`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

-- 
-- Table structure for table `players`
-- 

CREATE TABLE IF NOT EXISTS `players` (
`player_id` tinyint(3) unsigned NOT NULL auto_increment,
`guid` varchar(8) NOT NULL default '0',
`fixed_name` varchar(30) NOT NULL default '',
`hide` smallint(1) NOT NULL default '0',
PRIMARY KEY (`player_id`),
UNIQUE KEY (`guid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

-- 
-- Table structure for table `playerstats`
-- 

CREATE TABLE IF NOT EXISTS `playerstats` (
`pid` mediumint(9) unsigned NOT NULL auto_increment,
`guid` varchar(8) NOT NULL default '0',
`servernr` smallint(1) unsigned NOT NULL default '0',
`kills` mediumint(8) unsigned NOT NULL default '0',
`deaths` mediumint(8) unsigned NOT NULL default '0',
# And more stats...
PRIMARY KEY (`pid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

简而言之,服务器和玩家包含独特的实体,它们组合在玩家统计中(即特定服务器中玩家的统计数据)。除了统计数据之外,他们还被赋予了一个玩家 id (pid) 以供以后的数据库中使用。同样,该数据库包含表武器(唯一武器)和武器统计(服务器中武器的统计数据)、附件和附件统计以及地图和地图统计。一旦我完成了所有这些工作,我想在这些统计数据之间实现更多关系(即,使用 pid 和 wid 在特定服务器中特定武器的玩家统计数据)。

PHP 解析器通过 http 复制每个服务器的日志(有 6 个 atm),然后每 5 分钟读取一次(我对此还不太确定)。可以假设在这个解析过程中,每个表都必须被查询(使用 UPDATE 或 INSERT)至少一次(并且可能更多)。现在,我有很多关于如何发送查询的选项(我知道):

1:使用常规查询,即

    $statdb = new mysqli($sqlserver,$user,$pw, $db);
    foreach( $playerlist as $guid => $data ){
      $query = 'INSERT INTO `playerstats` 
                VALUES (NULL, '$guid', $servernr, $data[0], $data[1])';
      $statdb->query($query);
    }

2:使用多查询

    $statdb = new mysqli($sqlserver,$user,$pw, $db);
    foreach( $playerlist as $guid => $data ){
       $query = "INSERT INTO `playerstats` 
                 VALUES (NULL, '$guid', $servernr, $data[0], $data[1]);";
       $totalquery .= $query;
    }
    $statdb->multi_query($totalquery);

3:使用准备好的语句;我还没有真正尝试过这个。这似乎是一个好主意,但我必须为每张桌子准备一个声明(我认为)。这甚至可能吗?如果可以,它会有效吗?

4:正如您从上述代码中可能看到的那样,我最初将每个玩家、武器、地图等的所有统计数据都统计到一个数组中。一旦解析器读取了整个文件,它就会向 mysql 服务器发送一个带有这些累积统计信息的查询。但是,我在其他日志解析器中也看到(更多时候不是),只要解析了日志文件的新行,就会发送查询,例如:

    UPDATE playerstats 
    SET kills = kills+1 
    WHERE guid = $guid

这对我来说似乎效率不高,但是我又一次开始使用 php 和 sql,所以我知道什么:>

所以,简而言之;考虑到 logparser 逐行读取每一行,查询数据库的最有效方法是什么?当然,任何其他意见或建议总是受欢迎的。

4

2 回答 2

0

.5. 使用 mysql 对以下查询的支持创建单个多插入查询

INSERT INTO table (fields) VALUES(data),VALUES(data)...

它似乎是最有效的,包括准备好的语句

于 2013-01-21T15:21:25.630 回答
0

对我来说最有效的方法是每隔 5 分钟左右扫描一次服务器,然后将统计信息列表扫描到一个数组中(例如,在 5 分钟内有 38 个人在服务器上,所以你有一个数组38 个 ID,每个 ID 都有这 38 个 ID 的累积统计变化,需要在服务器中更新)。运行一个查询以检查用户是否在 stats 中具有现有 ID,然后再运行 2 个查询,一个用于创建新用户(多查询插入),一个用于更新用户(单个查询与 CASE 更新)。这将您限制为每 5 分钟 3 个查询。

于 2013-01-21T15:06:58.953 回答