web-dev-qa-db-ja.com

一時的なゴミは集められますか?

この質問は私に考えさせました wp_optionsの一時的なRSSフィードは自動的に削除されませんか?

トランジェントは期限切れになり削除されるはずです。ただし、これが処理される唯一の方法は、transientが期限切れになって要求されたときです。それから要求中に削除されます。

一時的な期限が切れたが、その後要求されない場合はどうなりますか?コーデックスの記述から、ある種のガベージコレクションが暗示されていると思いました。今、私はあまりよくわからず、そのようなことを実行するコードを見つけることができません。

それで、それは永遠にデータベースで立ち往生するだけでしょうか?

61
Rarst

彼らは今

WordPress 3.7以降、データベースのアップグレード時に期限切れのトランジェントが削除されます。 #20316 を参照してください。


古い答え

他に誰かが私に見せられないならば、結局のところ、トランジェントはガベージコレクションされていないようです。さらに悪いことに、オプションとは異なり、それらはデータベースに格納されることが保証されていません。そのため、すべてのトランジェントのリストを取得して有効期限を確認するための信頼できる方法はありません。

データベースがストレージとして使用されている場合にガベージコレクションを実行するための簡単なコードがいくつかあります。

add_action( 'wp_scheduled_delete', 'delete_expired_db_transients' );

function delete_expired_db_transients() {

    global $wpdb, $_wp_using_ext_object_cache;

    if( $_wp_using_ext_object_cache )
        return;

    $time = isset ( $_SERVER['REQUEST_TIME'] ) ? (int)$_SERVER['REQUEST_TIME'] : time() ;
    $expired = $wpdb->get_col( "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout%' AND option_value < {$time};" );

    foreach( $expired as $transient ) {

        $key = str_replace('_transient_timeout_', '', $transient);
        delete_transient($key);
    }
}
44
Rarst

いくつかのコメントをディスカッションから回答に移動し、言い換えと再フォーマットを行います。

基本的には、極端な場合を除いて、「ガベージコレクト」する必要はないということです。あなたがそれらを取得したことがないのであれば、それらが存在しているかどうかは関係ありません。

トランジェントはデフォルトでオプションテーブルに格納されています。基本インストールでは、オプションテーブルにはおそらく100個のエントリが含まれます。各トランジェントはさらに2つのエントリを追加しますが、数千のエントリがあっても、それらは自動ロードされないため、サイトの速度には影響しません。

WordPressは起動時にオプションをメモリにロードしますが、自動ロードフラグがオンになっているオプションのみをロードします。トランジェントはこれを取得しないので、メモリにロードされません。後で実際に使用されるトランジェントのみがコストを負担します。

データベースの観点からは、オプションテーブルには、オプションIDとオプション名の両方にインデックスがあります。トランジェントは常に名前(キー)に基づいてロードされるため、それらのルックアップは常に単一の一意のキー値に対する単純な選択です。したがって、ルックアップはO(log(n))で、非常に高速です。 log-nのBig-Oでは、目立つようになる前に何百万もの行に入る必要があります。率直に言って、実際のデータ転送とともに、クエリのセットアップと破棄のオーバーヘッドは、はるかに長くなります。照会自体は、比較により実質的にゼロ時間で実行されます。したがって、単にhaving余分な未使用行があっても、余分なディスク容量を使用しても何も影響を受けません。

データベースでの索引付けは、その裏で何が起こっているのか実際には理解していない人々には意味をなさない、このような深い読み方のアイデアの1つです。データベースは、ゼロからの高速データ検索のために設計されており、問題なくこの種のことを処理できます。これはかなり良い読みです: http://en.wikipedia.org/wiki/Index_(database

現在、最も明白な方法(それらに対してSQL DELETEを呼び出す)によるクリーンアップは、実際にデータベースからそれらを削除しません。インデックスからそれらを削除し、その行を "deleted"とマークするだけです。繰り返しますが、これはデータベースの仕組みです。実際にディスク領域を空にするには、次に続けてOPTIMIZE TABLEを実行する必要がありますが、これは高速な操作ではありません。時間がかかる。たぶんそれ以上の時間です。合計でCPU時間を節約するだけではおそらく十分ではありません。

使用されていない新しいトランジェントが継続的に挿入されているケースがいくつかある場合は、代わりに根本的な問題を見つける必要があります。これらの過渡現象を挿入していますか?彼らは変化しているか変化しているキーを使っていますか?もしそうなら、それを引き起こしているプラ​​グインやコードは、基本的には、そうしないで修正されるべきです。それらを適切に作成していないコードもそれらを取得していないため、必要以上に多くの作業を実行している可能性が高いため、これはより有用です。

その一方で、すべての投稿のようなものに対してトランジェントが作成されている場合があります。これは確かに完全に受け入れられるかもしれません。私はSFCでこれを自分で行い、Facebookから入ってくるコメントを保存します。各投稿はそれに関連した潜在的な一時的なものを持ちます。つまり、投稿ごとに2つの追加行があります。あなたが10kの投稿を持っている場合、あなたは(最終的には)オプションのテーブルに20kの行があるでしょう。これは悪くも遅くもありません。データベースが本当に気にする限り、100行と20,000行の間にはほとんど違いがないからです。すべて索引付きです。それはちょっと速いです。サブサブミリ秒。

あなたがmillion行に入り始めるとき、私は心配するでしょう。オプションテーブルのサイズが数百メガバイトを超えた場合は、もう少し詳しく検討する必要があります。しかし一般的に言って、これは極端な場合を除いて問題ではありません。何十万もの投稿がある大規模なニュースサイトのようなものよりも小さいものであれば、問題にならないことは確かです。そしてそれが問題になるほど十分に大きいサイトのために、あなたはある種の外部オブジェクトキャッシュを使用するべきであり、そしてthatケースでは、トランジェントは自動的にデータベースの代わりにそこに格納されます。

20
Otto

オットー - 私はあなたにこれ以上同意できませんでした。問題は、最終的にこれらすべてのトランジェントによって、テーブルのサイズがばかげていることです。無駄になるのに何百万行もかかりません。私は現在13万行以上を持ち、定期的にハングするオプションテーブルを扱っています。 valueフィールドは大きなテキスト型なので、「自動ロード」行だけを探してもパフォーマンスが悪くなります。これらの値フィールドは、残りの行データとは別に格納されます。論理的には同じテーブルの一部ですが、必要な行をプルアップするには結合が必要です。必要なデータがディスク上のいたるところに広がっているため、今では永遠にかかる結合。プロファイリング(mysql用のジェットプロファイラを使用)はこれを証明しています。

クラスタ化されたキーに自動ロードを追加すると、この問題を解決するのに役立ちます。たとえば、ID ASCなどの自動ロードDescでクラスタ化すると、すべての自動ロード行を最初にディスク上でまとめることができます。それでも私はあなたがDBの観点から大きな負担を見ていると思います。

個人的には私はこのシステムの設計は賢いと思います。オプション表は、多くのことをまとめた一般的なものになっているようです。 valueフィールドが残りの行データと同じページに含まれるのに十分に小さく、効果的にインデックスを付けることができればそれでも問題ありません。残念ながらそうではありません。これを設計する人は誰でもDB101クラスに戻る必要があります。

18
myke