1

現在、Call of Duty 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(サーバー内の武器の統計)、attachmentsとattachstats、mapsとmapstatsのテーブルが含まれています。これらすべてが機能するようになったら、これらの統計(つまり、pidとwidを使用した、特定のサーバー内の特定の武器に対するプレーヤーの統計)間の関係をさらに実装したいと思います。

PHPパーサーは、各サーバー(6 atmあります)のログをhttp経由でコピーし、5分ごとにそれらを読み取ります(まだよくわかりません)。この解析中に、すべてのテーブルを少なくとも1回(おそらくそれ以上)クエリする必要があると想定できます。現在、(私が知っている)クエリの送信方法についていくつかのオプションがあります。

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がすべての行を1つずつ読み取ることを考えると、データベースをクエリする最も効率的な方法は何でしょうか。もちろん、他のアドバイスや提案はいつでも歓迎します。

4

2 に答える 2

0

私にとって最も効率的な方法は、サーバーを頻繁に、5分ごとに1回程度スキャンしてから、統計のリストをスキャンして配列にすることです(たとえば、5分で38人がサーバーにいるので、 38個のID。それぞれに、サーバーで更新する必要のある38個のIDの統計情報の変更が累積されています)。1つのクエリを実行して、ユーザーが統計に既存のIDを持っているかどうかを確認し、さらに2つのクエリを実行します。1つは新しいユーザーを作成し(マルチクエリ挿入)、もう1つはユーザーを更新します(CASE更新を使用した単一クエリ)。これにより、5分ごとに3つのクエリに制限されます。

于 2013-01-21T15:06:58.953 に答える
0

.5。次のようなクエリに対するmysqlのサポートを使用して、単一の複数挿入クエリを作成します。

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

プリペアドステートメントを含め、それらすべての中で最も効率的だと思われます

于 2013-01-21T15:21:25.630 に答える