我正在尝试根据这个测试脚本优化我的 PHP<>MySQL:
<?
for($i=0;$i<100;$i++)//Iterations count
$res.= var_dump(loadRow("select body_ru from articles where id>$i*50 limit 100"));
print_r($res);
?>
我有 APC,并且 article 表有 id 索引。此外,所有这些查询都命中查询缓存,因此单独的 MySQL 性能非常好。
但是当我使用 ab -c 10 -t 10 来测试这个脚本时,我得到了:
100 次迭代:~100req/秒(每秒约 10'000 个 MySQL 查询)
5 次迭代:~200req/秒
1 次迭代:~380req/秒
0 次迭代:~580req/秒
我尝试禁用 PHP 中的持久连接 - 这会使它变慢一点。那么,如果 MySQL 不限制性能,我怎样才能让它运行得更快呢?
所以这看起来像是建立连接或其他事情花费了太多时间......
答案1
mysql_pconnect 将会更快,但是即将消失(而且我认为 mysqli 甚至不支持它)。持久连接会减少连接/拆除时间。
您的 mysql 是通过 TCP 还是套接字连接的?如果是 TCP,是否启用了压缩或 SSL?当您期望响应较大时,压缩是很好的选择,但是,对于较小的响应,您需要花费更多的 CPU 时间在两端进行压缩/解压缩。您希望在 99% 左右的时间中使用压缩。php 和 mysql 之间的 SSL 连接肯定会影响性能。
如果您通过 TCP 连接,mysql 中的 skip-name-resolve 会稍微加快速度。然后需要在授权中使用 IP 而不是域名。
但是,您认为这些查询可能位于缓存中取决于您的缓存大小和结果集大小。如果您的查询平均每个结果集有 400k 个查询(假设文章长度为 4k),则至少需要 40mb 的查询缓存来缓存内容。如果您要发回任何整数字段,请记住 libmysqlclient 库会将整数转换为 ascii,然后 php 必须在收到结果时将其转换为任何数据类型。
mysql_fetch_assoc 比 mysql_fetch_row 稍微慢一些,但是,还不至于让您觉得值得转换代码来使用它。
我认为您可能遇到了与 mysql 服务器连接的问题。如果您使用的是 TCP,则需要进行一些更改。如果您使用的是套接字连接,则可能无法对其进行太多性能调整。
@pQd,根据我的经验,我发现索引查询的限制子句上的查询优化器将从索引中得到答案,而使用范围索引不会对结果产生太大影响。范围查询也不会考虑后来被删除的文章 ID,这会导致分页失败。如果删除了第 100-150 篇文章中的 20 篇,则将返回 30 行,这可能无法正确填充您的页面。数据呈现的限制子句通常是正确的方法。mysql 执行整个查询的唯一时间是当您使用 sql_count_rows 时,这是另一个有用的分页工具。您需要确保从索引中回答这些查询以防止表扫描。
答案2
是的,我知道您说 mysql 不是限制因素但无论如何请尝试这个:
<?
for($i=0;$i<100;$i++){
$down = $i*50;
$up = ($i+1)*50;
print_r(var_dump(loadRow("select body_ru from articles where id>$down and $id<=$up "));
}
?>
mysql 以奇怪的方式处理限制...它将无论如何生成整个结果,然后仅将前 n 行发送到客户端。因此从上下边界对 id 进行过滤。
稍微更像 stackoverflow 的部分:
该代码并不 100% 等同于您的代码 - 就您而言,您一直在接收重叠的块。
loadRow 里面有什么 - 它使用 mysqli 吗?mysql 吗?一些像 adodb 这样的抽象吗?如果您调整性能,请跳过类似 adodb 的库。
此外 - 我更信任 innodb_buffer_pool 而不是查询缓存。
请让我们知道所提议的变更如何影响性能。