提问人:gvn 提问时间:8/24/2022 最后编辑:gvn 更新时间:8/26/2022 访问量:142
与 PDOStatement::bindParam() 相比,使用 PHP mysqli_stmt::bind_param() 时,MYSQL 查询性能非常差
MYSQL query performance very poor when using PHP mysqli_stmt::bind_param() compared to PDOStatement::bindParam()
问:
我在运行以下命令时遇到了与使用 PHP 相关的性能问题:mysqli_stmt::bind_param()
$sql = "select ts from scans where sessionid = ? order by id desc limit 1";
$stmt = $db->prepare($sql);
$stmt->bind_param("i", $row_sid );
$stmt->execute();
$result = $stmt->get_result()->fetch_array();
$stmt->close();
对于表中超过 20000 个点的最坏情况,此查询需要 2 秒,但这仅在使用 时发生。scans
row_sid = 10
mysqli_stmt::bind_param()
如果我将查询本身作为:
select ts from scans where sessionid = 10 order by id desc limit 1;
它在 0.016 秒后返回。
如果我不使用 bind 参数,也一样:
$sql = "select ts from scans where sessionid = 10 order by id desc limit 1";
$stmt = $db->prepare($sql);
$stmt->execute();
$result = $stmt->get_result()->fetch_array();
$stmt->close();
这也以毫秒为单位返回。
按照扫描表详细信息操作:
SHOW CREATE TABLE
scans | CREATE TABLE `scans` (
`id` int NOT NULL AUTO_INCREMENT,
`lid` int DEFAULT NULL,
`devid` int DEFAULT NULL,
`sessionid` int DEFAULT NULL,
`ts` int DEFAULT NULL,
`irpwr` double DEFAULT NULL,
`ir_v` double DEFAULT NULL,
`ir_i` double DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `scans_sessionid` (`sessionid`),
KEY `scans_devlid` (`devid`,`lid`),
KEY `scans_ts` (`ts`),
KEY `scans_lid` (`lid`)
) ENGINE=InnoDB AUTO_INCREMENT=43769072 DEFAULT CHARSET=utf8
编辑:
我使用 PDO 而不是 mysqli 进行了测试,性能得到了显着提高,无论是使用还是返回都接近直接查询速度。虽然,我没有找到任何显示性能差异原因的信息,因为 mysqli 已被证明在基准测试中更快。bindValue()
bindParam()
我可能遇到了一个我不明白的错误。
答:
-1赞
Rick James
8/26/2022
#1
为了“证明”“bind”是错误的,请在PHP代码中加入以分离出对bind的调用。microtime(true)
若要对任何 SQL 查询进行计时,请运行两次。有多个缓存会干扰获取实际时间。
如果数据尚未缓存在buffer_pool(或其他 RAM 缓存)中,则首次运行会因为 I/O 而变慢;第二个是对查询的生产使用情况的现实估计。
如果“查询缓存”为 ON,则无论查询有多复杂,第二次都将约为 1 毫秒。QC正在消失;计划将来将其移除。同时,做然后计时。
SELECT SQL_NO_CACHE ...
回到具体查询...
select ts
from scans
where sessionid = ?
order by id desc
limit 1
将运行得更快
INDEX(session_id, id, ts)
添加时,还要删除现有的 INDEX(session_id) 作为冗余。
评论
Even though I fixed the sessionid as 10 which is the biggest query
...可能是因为它只执行相同的查询 40 次,所以它只需要运行一次,然后每次都返回一些缓存数据。It returns in milliseconds.
-- 多少毫秒?如果执行查询 40 次,需要 2 秒,则解决方案平均每个查询需要 50 毫秒。bind_param
where sessionid in (<your 40 ids>)