【发布时间】:2019-07-24 12:31:23
【问题描述】:
我正在制作一些返回计数和按结果分组的 JSON 端点。对于这个端点,我使用 PDO 和命名占位符。使用命名占位符时,PHP 响应在execute 阶段最多需要六秒钟。当执行相同的查询并将值直接放入我的查询中时,响应几乎是瞬间的。
我正在更新仍然使用 mysql_query() 来使用 PDO 语句的旧代码。
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
$conn = new PDO('mysql:host=localhost;dbname=nameOfDB', 'username', 'password');
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->exec("set names utf8");
$query_slow = "SELECT t.meta as meta, count(*) as cnt
FROM field, repo, t, uplink, link
WHERE (
repo.rp1 = field.id OR
repo.rp2 = field.id OR
repo.rp3 = field.id OR
repo.rp4 = field.id)
AND repo.combination = t.meta
AND t.doc_id = uplink.doc_id
AND uplink.written = 1
AND uplink.link_id = link.id
AND field.id = :field
AND t.earliest > :min
AND t.latest < :max
GROUP BY t.meta
ORDER BY cnt desc";
if($parameters){
$stmt = $conn->prepare($query_slow);
$stmt->execute($parameters);
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($data, JSON_UNESCAPED_UNICODE );
}
如果我执行var_dump($parameters),则会返回以下内容:
$parameters = array(3) {
[":field"]=>
int(5)
[":min"]=>
int(-1000)
[":max"]=>
int(600)
}
这里是快速查询:
$query_fast = "SELECT t.meta as meta, count(*) as cnt
FROM field, repo, t, uplink, link
WHERE (
repo.rp1 = field.id OR
repo.rp2 = field.id OR
repo.rp3 = field.id OR
repo.rp4 = field.id)
AND repo.combination = t.meta
AND t.doc_id = uplink.doc_id
AND uplink.written = 1
AND uplink.link_id = link.id
AND field.id=5
and t.earliest > -1000
and t.latest <600
GROUP BY t.meta
ORDER BY cnt desc";
if(1==1){
// I ditched the $parameters, so my execute is empty.
$stmt = $conn->prepare($query_slow);
$stmt->execute();
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($data, JSON_UNESCAPED_UNICODE );
}
slow_query 最多可能需要 6 秒才能运行。如果我运行相同的查询并填写值和一个空的execute(),我的响应几乎是即时的。我对 PDO 做错了什么?
向execute() 提供数组时,我的页面响应缓慢。使用没有参数的查询时。响应是即时的。
@RiggsFolly 要求的我的计时码:
所以我在那里运行了计时代码:
if($parameters){
$time_prepare = microtime(true);
$stmt = $conn->prepare($querygraph);
$time_pre_exec = microtime(true);
$stmt->execute(($parameters));
//$stmt->execute();
$time_post_exec = microtime(true);
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
$time_post_fetch = microtime(true);
echo json_encode($data, JSON_UNESCAPED_UNICODE );
}
这是使用参数 5、-800 和 800(之前使用的相同)。我的计时码显示:
start: 1563972660.9188 (First line of the script)
prepare: 1563972660.9197 ==$time_prepare
pre execution: 1563972660.9201 ==$time_pre_exec
post execution: 1563972669.0058 ==$time_post_exec ==> 9 seconds!
post fetch: 1563972669.0058
在没有占位符的查询上使用相同的参数时,我使用相同的查询和一个空的 execute()。我用我在准备好的语句中使用的相同值替换了占位符。时序如下:
prepare: 1563973120.2965
pre execution: 1563973120.2969 //before execution()
post execution: 1563973120.312 //after executeion()
post fetch: 1563973120.3121
【问题讨论】:
-
我使用
$db->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND,'SET NAMES UTF8');可能对速度没有帮助 -
为什么不用
JOIN来代替? -
我在这里没有看到任何计时码。如果您添加了一些,这将有助于确定时间消耗在哪里
-
尝试使用适当的绑定类型分别绑定变量。我怀疑这会有所帮助,但有一些谣言
-
@Qirel;将查询结构更改为
JOIN将如何改进execute()phase。如果我在 PHPmyadmin 中执行此查询或使用填充的值而不是占位符执行相同的查询,则速度非常好。