mysql永久准备语句

Posted

技术标签:

【中文标题】mysql永久准备语句【英文标题】:mysql permanently prepared statements 【发布时间】:2012-07-21 06:58:21 【问题描述】:

我希望在高流量站点上使用准备好的语句来加速一些查询。我认为我没有正确理解的是使用准备好的语句的好处,除非它们可以通过多个连接保持准备状态。看起来这对于也不允许持久连接的 PDO 是不可能的。但持久连接功能不允许 PDO。

为了论证,我每秒运行 5,000 次查询: SELECT * FROM some_table WHERE some_column LIKE 'some_value'

据我了解,如果我每次需要查询时都更改“some_value”,PDO 会阻止 mysql 重新编译和评估查询。我也知道“some_value”可以以二进制而不是 ASCII 传输以节省带宽,但如果我每次打开连接时都必须发送整个查询,它不会节省太多。

根据我的阅读,存储过程也不是解决方案,因为它们也不会通过多个连接保持编译。

这个问题有什么解决办法吗?将准备好的语句存储在服务器上的某个地方,并让它在内存中编译并准备好在收到变量后立即触发?

有没有办法通过将连接池与 PDO 相结合来实现这一点? (虽然我也听说连接池并不理想,因为它会在某些情况下导致阻塞)

【问题讨论】:

如果您希望使用持久连接,您必须在传递给 PDO 构造函数的驱动程序选项数组中设置 PDO::ATTR_PERSISTENT。如果在对象实例化后使用 PDO::setAttribute() 设置此属性,驱动程序将不会使用持久连接。 【参考方案1】:

不,没有办法使用持久的预处理语句。

但是,对于每秒运行 5000 次的查询,有一个理想的解决方案 - Handlersocket

【讨论】:

【参考方案2】:

在运行大量基准测试后,我们发现在服务器上准备的预处理语句为我们提供了最大的速度优势。这是一个例子:

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 ;

【讨论】:

每个本地准备好的语句都在服务器上准备。但是,它不会使它们在连接之间保持持久。【参考方案3】:

在 MySQL 中使用准备好的语句不太可能使您的查询变得更快,而且它也会阻止查询缓存工作。如果您确实需要以 5k/s 的速度运行相同的查询,则需要在数据库前面进行一些缓存。 Memcached 很流行,Redis 也很流行。根据您的操作,缓存元素或整个页面也可能是一种选择。

【讨论】:

这不是真的,大多数准备好的语句缓存了!见dev.mysql.com/doc/refman/5.1/en/query-cache-operation.html

以上是关于mysql永久准备语句的主要内容,如果未能解决你的问题,请参考以下文章

Mysql介绍及其Sql语句

三万字91道MySQL面试题。 附PDF

Linux永久修改Mysql最大连接数

Linux永久修改Mysql最大连接数

使用 group by 汇总列并存储为 MySQL 中的新列(永久)

第13期:最全91道MySQL面试题 | 附答案解析