もともと、私は Web ページのパフォーマンスをより良く最適化する方法を知りませんでした。そして最近、Python と PHP で同様の Web ページのレンダリング速度を比較していたときに、これまで発見したことのない非常に単純で馬鹿げた方法を偶然発見しました。私は自分自身を観察する必要があります): Discuz フォーラムなどの一部の PHP アプリケーションと同様に、生成された Web ページに「このページが何秒生成されたか」を出力し、テストのために Web ページにアクセスし続けると、直感的にどのような操作でボトルネックが発生するのか、ボトルネックを解決する方法を調べます。
そこで、SimpleCD がホームページを生成すると、予想外に約 0.2 秒かかったことがわかりました。これは本当に耐え難いものでした。Discuz フォーラムのホームページの平均的な生成に比べて、かかる時間はわずか 0.02 秒で、Discuz フォーラムのホームページは間違いなくはるかに長いものです。 SimpleCD のホームページよりも複雑です。このギャップは Python 言語によって引き起こされたものではなく、Discuz プログラムが適切に最適化されているとしか言えません。
実際、ホームページを生成するときに、SimpleCD は 3 つの SQLite データベースで 42 を超えるクエリを実行する必要があることは、分析しなくてもわかります。これは、歴史的な理由により非常に非効率な設計です。 ; しかし、これ 40 を超えるクエリのうち、ほとんどは実際には非常に高速なクエリであり、パフォーマンスが優れているクエリが 2 つあり、その他は遅くありません。
最初の大きな操作は次のとおりです: データの数を取得します
SELECT count(*) FROM Verycd
この操作には毎回時間がかかります。毎回データベースをロックする必要があり、主キーの統計が更新されるためです。データの数が多いため、かかる時間は O(N) であり、N はデータベースのサイズになります。この問題を解決するには、現在のデータ数を任意の場所に保存するだけです。データの追加または削除時に変更を加えるだけなので、時間は O(1) です
2 番目の大きな問題は、最新の更新された 20 個のデータ リストを取得する
SELECT です。 title,brief,updtime FROM Verycd
ORDER BY updtime DESC LIMIT 20;
インデックスは updtime に実行されるため、実際のクエリ時間は実際にはインデックスの検索時間になります。しかし、なぜこの操作は遅いのでしょうか?データは公開時間に従って挿入されているため、更新時間に従って表示すると、少なくとも 20 か所で I/O を実行する必要があり、遅くなります。解決策は、I/O を 1 か所で実行できるようにすることです。つまり、新しいデータがデータベースに追加されない限り、または元のデータが変更されない限り、このステートメントの戻り結果はキャッシュされます。これは 20 倍高速です:)
次は 20 の小さなケースです: パブリッシャーとクリック数の情報を取得します
SELECT owner FROM LOCK WHERE id=XXXX;
SELECT ヒット FROM stat WHERE id=XXXX;ここで使用されている SQL 結合ステートメントは、トラブルを避けるために使用されているのではありませんか?アーキテクチャ上の理由により、これらのデータは別のデータベースに配置されます。Stat は頻繁に挿入する必要があるため、mysql に保存されます。 mysql の悲劇的なインデックスの使用法。ページング効率の関係で sqlite3 データベースに保存されているため、結合できません -.-
いよいよ memcached の番です。キャッシュする予定なので、キャッシュにファイルを使用する場合は、引き続きディスク I/O が発生します。メモリ I/O が大幅に高速になります。つまり、memcached はその名前が示すとおり、まさにそれです。
Python Web アプリケーションでは
memcache は実際にはマップ構造であり、最も一般的に使用されるのは次の 2 つです。関数:
sql = 'select count(*) from Verycd'
c = sqlite3.connect('verycd.db').cursor()
# 独自の処理メソッド
c.execute(sql)
count = c.fetchone()[0]
# 現在の処理メソッド
from hashlib import md5
key=md5(sql)
count = mc.get(key)
if not count:
c. execute(sql)
count = c.fetchone()[0]
mc.set(key,count,60*5) #5 分間保存します
ここで、md5 はキーの配布をより均一にするためのもので、その他はコードは非常に直感的なので説明は省略します。
ステートメント 1 とステートメント 2 を最適化した後、ホームページの平均生成時間は 0.02 秒に短縮され、これはステートメント 3 を最適化した後の discuz と同じ桁数であり、最終的な結果はホームです。 memcached コードを数行最適化しただけで、ページの生成時間が約 0.006 秒に短縮され、パフォーマンスが 3300% 向上しました。やっと背筋を伸ばしてDiscuzを見ることができます