2011-09-13 16 views
0

コードをループするたびに複数の更新が発生します。質問を書く時に、私は80の別々の更新が1つのテーブルから起こっています。MySQLの複数の更新が長すぎます

これは10.8秒かかります。アップデートをしないと(画面に出力されるので、プログラムが何をしているかを見ることができます)、2.7秒かかります。 8秒が長すぎるためにデータベースをロックしている:(

更新の例です

UPDATE players SET energy=energy+14 WHERE playerID=243 LIMIT 1 
UPDATE players SET energy=energy+7 WHERE playerID=258 LIMIT 1 
UPDATE players SET energy=energy+3986 WHERE playerID=244 LIMIT 1 
UPDATE players SET energy=energy+2990 WHERE playerID=245 LIMIT 1 

+0

これはデータベースに必要ですか?おそらく** memcachedレイヤー**の間に、このような素早く変化するプレーヤーデータを保存したいと思うかもしれません。その後、memcachedの値を定期的に保存することができます(例えば、プレーヤーがログオフしたり、大規模なイベントが発生した場合) – Konerak

+0

データベースが必要な場合: 'SHOW FULL PROCESSLIST'の出力全体を表示できますか?選択/挿入ではなく、ブロックしている更新ですか? 'SHOW CREATE TABLE players'の出力を表示して、データ型とインデックスをチェックできますか? – Konerak

+0

また、1つのデータベース接続ですべての更新を実行していることを確認してください。 –

答えて

1

一つのオプションをこれをスピードアップする方法上の任意のアイデアはあなたのことを確認することです選手のenergy行上の任意のインデックスを持っている、とあなたは(インデックスは検索回数を減少させますが、更新を増加/回を挿入する)playerIDにインデックスを持っていることを確認してください。

また、私はを読んでお勧めしません。いくつかのアイディアについてはを参照してください。 1つの提案は、テーブルをロックし、すべてを更新してからロックを解除することです。実行しているMySQLのバージョン(使用しているデータベース/テーブルの種類(MyIsam/InnoDBなど))に関する情報をいくつか教えてもらえれば、さらに手助けをすることができます。

こちらがお役に立てば幸いです。

+0

「インデックスが検索時間を短縮する」という意味ですか? –

+0

「更新/挿入を増やしてください」と思っています。 @Chrisはおそらくそれらを切り替えた? – Konerak

+0

ああ、申し訳ありません...私はそれらを回した。ハハ、ありがとう。 – Chris

2

LIMIT 1句の利点は何ですか?もうやめろ。

playerIDにインデックスがありますか?そうでない場合は、追加します。

Playersのテーブルの大きさはどれですか?何行ですか?各列の大きさはどれくらいですか?

あなたが操作をパラメータ化準備UPDATE文を考えがあります:

UPDATE Players SET Energy = Energy + ? WHERE PlayerID = ? 
あなたはその後、別のパラメータを指定して、この複数回実行することができ

14 243 
    7 258 
3986 244 
2990 245 

プリペアドステートメントを使用することの利点は、 DBMSは毎回SQLを再解析する必要がないため、行う作業が少なくなります。

+0

索引と準備が良い音ですが、私は 'LIMIT 1'を落とすことでどんな利点があるのか​​分かりません。最悪でも影響はなく、せいぜい早期復帰の原因となります。 – Konerak

+0

テーブルのスキーマはありませんが、おそらくPlayerIDが主キーであるか、または一意制約が設定されていると考えられます。そうであれば、LIMIT 1の解析には余分な作業がありますが(多くはありませんが...)、結果は変わりません。一意の列でない場合、LIMIT 1はデータベースが破損する原因となります(Energy列の値が異なる、指定されたPlayerIDの行が異なる可能性があります)また、LIMIT句はSQLの移植性を不必要に制限します。 –

+0

私は次のコードを$ stmt = $ mysqli-> prepare( "UPDATE player SET energy =:エネルギー、信頼=:自信、士気=:playerID"); \t \t \t \t $ stmt- > bindParam( ':エネルギー'、$エネルギー); \t \t \t \t \t $ stmt-> bindParam( ':自信'、$信頼); \t \t \t \t \t $ stmt-> bindParam( ':morale'、$ morale); \t \t \t \t \t $ stmt-> bindParam( ':playerID'、$ playerID); \t \t \t \t $ playerID = 1; #キーは選手IDです $ energy = 1000; $ confidence = 1100; $ morale = 1200; $ stmt-> execute();これは致命的なエラーをもたらします:非オブジェクト上のメンバ関数prepare()を呼び出す –

関連する問題