2011-02-03 1 views
1

私は、MySQLデータベースからPHPファイルを作成しています。各ファイルは225kbです。私は40のファイルを作成します。MySQL、LIMIT 0,1800〜LIMIT 72000,18000をループ(40回)で使用してフラットファイルを作成するには、より多くのDBのfirendly方法が必要ですか?

基本的には、最初にLIMIT 0、1800を持つクエリを呼び出すPHPスクリプトを実行しています。ループして40回実行し、最後のクエリはLIMIT 72000,1800を使用します。

ループでは、私は0.7秒間スリープします。プロセス全体には45秒かかります。

私が製作した一部のデバッグ情報

Query took 0.03 second for ../sitemap-0.xml done! 
Query took 0.06 second for ../sitemap-1800.xml done! 
..snip .. 
Query took 0.9 second for ../sitemap-70200.xml done! 
Query took 0.9 second for ../sitemap-72000.xml done! 
Took: 44.7057 

あなたは、クエリに時間がかかると長いジョブを実行するように、これはクエリはLIMITの位置を決定するために見てする必要のあるデータの量でなければなりませんがわかります。その結果、CPU使用率はクエリごとに増加します。

サーバーの最大CPU時間制限は60秒です。

私の主な考慮事項は、CPU時間とデータベースのクエリ時間をできるだけ短く保つことです。高い価値を持つことは容認できません。

クエリを何度も実行すると、リソースが少し浪費されているようです。

これを行うより良い方法はありますか?

+0

、なぜあなたは、サイクルごとに1800に制限されています? –

+0

このタスクを実行する頻度はどのくらいですか? – webbiedave

+0

1800というのは、ファイルサイズとファイルの量に見合ったものだったからです。私は仕事を1日に1回実行することを考えています。 – Jules

答えて

3

より良い解決策は、バッファリングされていない結果を使用することです(その結果、すべての結果が転送を完了するのを待たずに結果を返します)。あなたがmysql拡張子を使用している場合

ので、(mysql_unbuffered_queryを使用して):

$sql = 'SELECT a, bunch, of, data FROM a_big_table WHERE some_condition'; 
$result = mysql_unbuffered_query($sql); 
$data = array(); 
$count = 0; 
while ($row = mysql_fetch_assoc($result)) { 
    $count++; 
    $data[] = $row; 
    if ($count >= 1800) { 
     storeData($data); 
     $data = array(); 
     $count = 0; 
    } 
} 
if ($count > 0) { 
    storeData($data); 
} 

が機能storeDataは、実際にファイルを書き込みところ。

この利点は2倍です。まず、クエリは1回だけ実行されるので、何度も再実行する必要はありません。次に、バッファリングされていないので、クエリ全体が終了するのを待つのではなく、すぐに結果を取得することができます。

+0

明らかに、私がサイトマップを作成し、データベースからページ名を取得していることを伝えることができなければなりません。おそらくフィールドでなければならないのですか? XMLサイトマップを作成するために私の書式をどのように追加するのか分かりません。 – Jules

+0

@Jules:これは 'storeData'関数で行われます。その関数に渡される配列は、行の配列です。だから 'foreach($行としての$ data){エコー$行['タイトル']; } '(' title'はクエリの値であると仮定します)。基本的には、各行の配列を作成するだけです。そして、バッチでそれらを処理する... – ircmaxell

0

あなただけは、MySQL 5.1+持っているならば、あなたはそれを直接行うことができ、XMLでデータが必要な場合:your_user-pを追加し、あなたが入力したユーザパスワードが必要な場合は

mysql -uyour_user your_database -e "SELECT * FROM table WHERE something > 0" --xml > /path/to/file.xml 

を。明らかに実際のクエリにSELECT * FROM table WHERE something > 0を変更してください。詳しくは、this articleで読むことができます。

SELECT some expression FROM table WHERE condition LIMIT offset, count INTO OUTFILE '/path/to/file.txt' 

PHPは次のよ​​うになります:

0

あなたはMySQLを使用してではなく、PHPに結果をロードするより速くそれを行うことができます好奇心のうち

for ($i = 0; $i < 72000; $i+=1800) { 
    $sql = "SELECT some expression FROM table WHERE condition LIMIT $i, 1800 INTO OUTFILE '/path/to/sitemap-$i.xml'"; 
    mysql_query($sql); 
} 
関連する問題