5

トラフィックの多いサイトでプリペアドステートメントを使用して、いくつかのクエリを高速化することを検討しています。私が正しく理解していないと思うのは、複数の接続で準備ができていない限り、準備されたステートメントを使用することの利点です。これは、持続的接続も許可しないPDOでは不可能のようです。しかし、持続的接続機能はPDOを許可しません。

引数のために、1秒間に5,000回クエリを実行しているとしましょう:SELECT * FROM some_table WHERE some_column LIKE'some_value'

私が理解していることから、クエリが必要になるたびに「some_value」を変更した場合、PDOはmysqlがクエリを再コンパイルして評価するのを防ぎます。また、帯域幅を節約するために「some_value」をASCIIではなくバイナリで送信できることも理解していますが、接続を開くたびにクエリ全体を送信する必要がある場合は、それほど節約にはなりません。

また、私が読んだことから、ストアドプロシージャは、複数の接続を介してコンパイルされたままにならないため、解決策ではありません。

この問題の解決策はありますか?プリペアドステートメントをサーバーのどこかに保存し、メモリにコンパイルされたままにして、変数を受け取るとすぐに起動できるようにしますか?

接続プールとPDOを組み合わせてこれを実現する方法はありますか?(接続プールは特定の条件でブロッキングを引き起こす可能性があるため、理想的ではないとも聞いていますが)

4

3 に答える 3

5

多数のベンチマークを実行した後、サーバー上で準備されたステートメントが最大の速度メリットをもたらすことがわかりました。次に例を示します。

DROP PROCEDURE IF EXISTS get_user;

DELIMITER //

CREATE PROCEDURE get_user(IN v_user VARCHAR(255))
DETERMINISTIC
READS SQL DATA
SQL SECURITY INVOKER
COMMENT ''
proc: BEGIN
    SET @user = v_user;

    IF ISNULL(@get_user_prepared) THEN
        SET @get_user_prepared = TRUE;

        SET @sql = "SELECT * FROM mysql.user WHERE user = ?";

        PREPARE get_user_stmt FROM @sql;
    END IF;

    EXECUTE get_user_stmt USING @user;
END;
//

DELIMITER ;
于 2012-07-23T05:46:58.603 に答える
0

MySQL で準備済みステートメントを使用しても、クエリが大幅に高速化される可能性は低く、クエリ キャッシュも機能しなくなります。同じクエリを 5k/s で実行する必要がある場合は、データベースの前にキャッシュが必要です。Memcached は人気があり、Redis も同様です。何をしているかによっては、要素またはページ全体をキャッシュすることもオプションになる場合があります。

于 2012-07-23T03:06:06.060 に答える
0

いいえ、永続的な準備済みステートメントを使用する方法はありません。

ただし、1 秒あたり 5,000 回実行されるクエリには理想的なソリューションがあります - Handlersocket

于 2013-05-21T19:08:55.663 に答える