PHPからMySQLのクエリ送信のバッファリングについて

PHP-users 32941を見て、クエリ結果のバッファリングってどうなってるんだろうと思ったので調べてみた。詳細は以下によるが、何も考えずデフォルトでクエリ結果を取得する限りはバッファリングあり、つまりクエリ結果をPHPが一括で読み込んでいる。

なお、ここで言っているバッファリングありとは、MySQLAPIレベルで行っているものである。従って、次のようなPHPスクリプトを書いたからといって、バッファリングなし。とはならない。(以下のように書いてもバッファリングありです)

$result = mysql_query($sql)
while ($row = mysql_fetch_array($result)) {
  ;
}

クエリの戻りが大きいSQLのときは、バッファリングなしでやってみるとよい結果がでるかもしれない。もっとも、バッファリングなしでは、PHPの負担は減るが、MySQLサーバ側に負担がかかるっぽいので、単純に置換すればよいというものでもなさげ。

PHPからMySQLを使う手段は、mysql、mysqli、PDO の3種類。これらについて調べる。

まず、一番低レベルなMySQLのネイティブAPIレベルでは、次のようにバッファありなしの2種類の関数がある。

mysql の場合、

mysqli の場合、

PDO の場合、

PHPのソースから、mysql_use_result とmysql_store_result を抽出

php-5.2.4\README.STREAMS(325): state->result = mysql_use_result(&state->conn);
php-5.2.4\ext\mysql\php_mysql.c(112): #define MYSQL_USE_RESULT	0
php-5.2.4\ext\mysql\php_mysql.c(113): #define MYSQL_STORE_RESULT	1
php-5.2.4\ext\mysql\php_mysql.c(1306):     			mysql_result = mysql_use_result(&mysql->conn);
php-5.2.4\ext\mysql\php_mysql.c(1341): 	if(use_store == MYSQL_USE_RESULT) {
php-5.2.4\ext\mysql\php_mysql.c(1342): 		mysql_result=mysql_use_result(&mysql->conn);
php-5.2.4\ext\mysql\php_mysql.c(1344): 		mysql_result=mysql_store_result(&mysql->conn);
php-5.2.4\ext\mysql\php_mysql.c(1356): 	if (use_store == MYSQL_USE_RESULT) {
php-5.2.4\ext\mysql\php_mysql.c(1395): 	php_mysql_do_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQL_STORE_RESULT);
php-5.2.4\ext\mysql\php_mysql.c(1404): 	php_mysql_do_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQL_USE_RESULT);
php-5.2.4\ext\mysql\php_mysql.c(1439): 	php_mysql_do_query_general(query, mysql_link, id, db, MYSQL_STORE_RESULT, return_value TSRMLS_CC);
php-5.2.4\ext\mysqli\mysqli.c(823): 	result = (resmode == MYSQLI_STORE_RESULT) ? mysql_store_result(mysql->mysql) :
php-5.2.4\ext\mysqli\mysqli.c(824): 												mysql_use_result(mysql->mysql);
php-5.2.4\ext\mysqli\mysqli_api.c(498): 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
php-5.2.4\ext\mysqli\mysqli_api.c(1268): 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
php-5.2.4\ext\mysqli\mysqli_api.c(2048): 	if (!(result = mysql_store_result(mysql->mysql))) {
php-5.2.4\ext\mysqli\mysqli_api.c(2102): 	if (!(result = mysql_use_result(mysql->mysql))) {
php-5.2.4\ext\mysqli\mysqli_nonapi.c(249): 	result = (resultmode == MYSQLI_USE_RESULT) ? mysql_use_result(mysql->mysql) : mysql_store_result(mysql->mysql);
php-5.2.4\ext\mysqli\mysqli_warning.c(74): 	result = mysql_store_result(mysql);
php-5.2.4\ext\pdo_mysql\mysql_statement.c(78): 			res = mysql_store_result(S->H->server);
php-5.2.4\ext\pdo_mysql\mysql_statement.c(225): 			S->result = mysql_use_result(H->server);
php-5.2.4\ext\pdo_mysql\mysql_statement.c(227): 			S->result = mysql_store_result(H->server);
php-5.2.4\ext\pdo_mysql\mysql_statement.c(277): 			S->result = mysql_use_result(H->server);
php-5.2.4\ext\pdo_mysql\mysql_statement.c(280): 			S->result = mysql_store_result(H->server);
php-5.2.4\ext\pdo_mysql\mysql_statement.c(624): 		res = mysql_store_result(S->H->server);
php-5.2.4\ext\sybase\php_sybase_db.c(810): 	/* The following is more or less the equivalent of mysql_store_result().
php-5.2.4\ext\sybase_ct\php_sybase_ct.c(1235): 	/* The following (if unbuffered) is more or less the equivalent of mysql_store_result().