PDO连接首先查询延迟

时间:2013-04-17 14:39:35

标签: php mysql pdo

我有一个使用PHP的PDO库来访问mysql数据库的站点。 mysql数据库经过高度优化,具有所有合适的索引,可以快速查询查询等。我遇到了一些奇怪的行为,虽然与第一个运行特定Web服务的查询有关。

此特定Web服务针对数据库运行查询并返回json响应,然后将其反馈给jquery自动完成。

首次在客户端运行时的查询需要大约2秒才能运行,之后它会下降到百分之一秒,大概是由于innodb缓存。

如果我在新会话期间输入自动完成框中的条目,则第一个查询响应可能需要超过5秒,之后返回响应变得非常快。如果我然后离开网站一段时间,也许是一个小时(不是一个精确的措施,但为了争论,相对较长的一段时间)并回到它,再次观察到同样缓慢的第一个查询行为。

我正在使用持久连接,并且由于连接服务器上的连接数量有限。

我想知道你们中是否有人有任何想法可以让我更多地减轻初始延迟。

$DBH = null;

$host = "127.0.0.1";
$db_name = "my_db";
$user_name = "me";
$pass_word = "something";

try {
  # MySQL with PDO_MYSQL
  $DBH = new PDO("mysql:host=$host;dbname=$db_name;charset=utf8", $user_name, $pass_word, array(PDO::ATTR_PERSISTENT => true, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
  $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch(PDOException $e) {
    error_log( $e->getMessage(), 0 );
}

更新了回答

经过多次测试并且在彻底检查到它不是dns问题后,我正在检查innodb缓冲池路径。无论如何,我写了一个存储过程,它使用一个查询为数据库中的每个表生成一个查询,从而导致它们被缓存在innodb_buffer_pool中。为每个表生成sql查询的查询来自following SO question。我只对该查询进行了一次编辑,并放入了database()函数,以便它可以从调用它的任何数据库中工作。

我也进行了设置,以便可以通过PHP调用它,而无需等待脚本完成,因此您的正常应用程序将继续运行。

我希望这可以帮助别人。另外,为了提高效率,你可以将exec冷却到一个小函数中,只在特定时间运行它等等。

MySQL存储过程SQL

DELIMITER $$

USE `your_db_name`$$

DROP PROCEDURE IF EXISTS `innodb_buffer_pool_warm_up`$$

CREATE DEFINER=`user_name`@`localhost` PROCEDURE `innodb_buffer_pool_warm_up`()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE sql_query VARCHAR(1000) DEFAULT NULL;
DECLARE sql_cursor CURSOR FOR
SELECT 
  CONCAT('SELECT `',MIN(c.COLUMN_NAME),'` FROM `',c.TABLE_NAME,'` WHERE `',MIN(c.COLUMN_NAME),'` IS NOT NULL')
FROM
  information_schema.COLUMNS AS c
LEFT JOIN (
  SELECT DISTINCT
    TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME
  FROM
    information_schema.KEY_COLUMN_USAGE
) AS k
USING
  (TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME)
WHERE
  c.TABLE_SCHEMA = DATABASE()
  AND k.COLUMN_NAME IS NULL
GROUP BY
  c.TABLE_NAME;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN sql_cursor;
read_loop: LOOP
    FETCH sql_cursor INTO sql_query;
    IF done THEN
      LEAVE read_loop;
    END IF;

SET @stmt_sql = sql_query;
PREPARE stmt FROM @stmt_sql;
EXECUTE stmt;

END LOOP;
CLOSE sql_cursor;
END$$
DELIMITER ;

PHP调用存储过程

innodb_warm_up_proc_call.php

<?php
$DBH = null;

$host = "localhost";
$db_name = "your_db_name";
$user_name = "user_name";
$pass_word = "password";

try {
  # MySQL with PDO_MYSQL
  $DBH = new PDO("mysql:host=$host;dbname=$db_name;charset=utf8", $user_name, $pass_word, array(PDO::ATTR_PERSISTENT => true, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
  $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

  $sql = "CALL innodb_buffer_pool_warm_up()";
  $STH = $DBH->prepare( $sql );
  $STH->execute();

    }catch( PDOException $e ) {
        error_log( $e->getMessage() . ' in ' .$e->getFile(). ' on line ' .$e->getLine(), 0 );
    }
?>

PHP以静默方式运行上述脚本而无需等待其完成

innodb_warm_up.php

<?php

$file_to_execute = dirname(__FILE__) . "/innodb_warm_up_proc_call.php";

//Run the stored procedure but don't wait around for a chat
exec("php -f {$file_to_execute} >/dev/null 2>&1 &");

?>

2 个答案:

答案 0 :(得分:0)

在处理特定网络服务时,请将其域名更改为IP地址 最有可能的是它会消除这种延迟(由DNS查找引起)

答案 1 :(得分:0)

感谢您对此提供的所有帮助和建议。我彻底检查了dns和其他解决方案,但最后它结果是innodb页面缓冲池。我为自己编写了一个解决方案,并在上面的问题中完整地添加了它,所以希望它会有用。 再次感谢您的帮助。