2013-01-21 30 views
1

我目前正在嘗試爲使命召喚4創建一個logparser。解析器本身在php中,並通過特定服務器的日誌文件的每一行讀取,並將所有統計信息寫入一個有mysqli的數據庫。數據庫已經存在,我很確定(有限的經驗)他們組織良好。但是,我不確定以什麼方式將更新/插入查詢發送到數據庫,或者更確切地說,哪種方式是最優的。高效地從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)供以後的數據庫使用。同樣,該數據庫包含表格武器(獨特武器)和武器庫(武器在服務器中的統計數據),附件和附件,以及地圖和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:使用準備好的語句;我還沒有嘗試過。這似乎是一個好主意,但是我必須爲每張桌子做一個準備好的陳述(我認爲)。這甚至是可能的,如果是的話,它會有效嗎?你可能會從上述代碼中看到,我最初將每個玩家,武器,地圖等的所有統計數據統計到一個數組中。一旦解析器讀完了整個文件,它就會向這個mysql服務器發送一個包含這些累積統計信息的查詢。但是,我也看到了(更多的時候則沒有)其他logparsers,每當日誌文件的新行被解析,所以像查詢被髮送:

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

這似乎並不非常有效對我來說,但後來我只是開始與PHP和SQL,所以我知道什麼:>

因此,總之;考慮到logparser逐一讀取每一行,什麼是查詢數據庫最有效的方式?當然,任何其他建議或建議總是受歡迎的。

回答

0

.5。創建多插入查詢使用MySQL的的查詢,如

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

看來最有效的他們,包括預處理語句

+0

權的支持,我沒有想到這一點。這也會與更新兼容嗎?即INSERT INTO TABLE(fields)VALUES(data1),VALUES(data2).... VALUES(dataN)ON DUPLICATE KEYS UPDATE field1 = field1 + VALUES(field1)'? – user1997279

0

對我來說,最有效的方法是每隔5分鐘左右掃描一次服務器,然後將統計列表掃描到一個數組中(例如,在5分鐘內38人已經在服務器上,所以你具有38個ID的陣列,每個ID都有需要在服務器中更新的這38個ID的累計統計變化)。運行一個查詢來檢查用戶是否具有統計信息中的現有標識,然後再添加2個查詢,一個用於創建新用戶(多查詢插入),另一個用於更新用戶(帶有CASE更新的單個查詢)。這限制你每5分鐘進行3次查詢。