有效地从php发送多个mysql查询


Efficiently send multiple mysqli queries from php

我目前正尝试着为《使命召唤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;

简而言之,服务器和玩家包含独特的实体,它们在playerstats中组合(即特定服务器中玩家的统计数据)。除了统计数据之外,他们还会得到一个玩家id (pid),以便在以后的数据库中使用。类似地,数据库包含表weapons(唯一的武器)和weaponstats(服务器中武器的统计数据)、attachment和attachstats、map和mapstats。一旦我得到所有这些工作,我想实现这些统计数据之间的更多关系(即玩家的统计数据在特定的服务器上的特定武器,使用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开始,所以我知道:>

所以,简而言之;考虑到日志解析器将逐个读取每一行,那么查询数据库的最有效方法是什么?当然,任何其他意见或建议都是欢迎的。

使用mysql对

等查询的支持创建一个单个多插入查询
INSERT INTO table (fields) VALUES(data),VALUES(data)...

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

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