哪个更快/更高效 - 很多小MySQL查询或一个大PHP数组?

时间:2012-08-21 08:54:01

标签: php mysql arrays performance

我有一个基于PHP / MySQL的Web应用程序,它通过MySQL表格提供多种语言支持" language_strings"使用string_id,lang_id,lang_text字段。然后,当我需要以所选语言显示字符串时,我调用以下函数...

public function get_lang_string($string_id,$lang_id) {
    $db=new Database();     
    $sql=sprintf("SELECT lang_string FROM language_strings WHERE lang_id IN (1, %s) AND string_id=%s ORDER BY lang_id DESC LIMIT 1", $db->escape($lang_id, "int"), $db->escape($string_id,"int"));
    $row=$db->query_first($sql);
    return $row['lang_string'];
} 

这很好用,但我担心可能会有很多数据库查询。例如主菜单有5个链接文本,所有这些都调用此功能。

将选定的lang_id的整个language_strings表结果加载到PHP数组然后从函数中调用它会更快吗?可能会是一个巨大的数组,其中大部分都是多余的,但很明显,每个页面加载而不是很多数据库查询。

有人可以提出另一种更有效的方法吗?

6 个答案:

答案 0 :(得分:7)

没有一个不区分大小写的答案。你可以在个案陈述中真正看一下它。话虽如此,大多数情况下,在一个查询中获取所有数据,将其弹出到数组或对象中并从那里引用它会更快。

需要注意的是,您是否可以像运行五个单独的查询一样快速地在一个查询中提取所需的所有数据。这就是查询本身的性能发挥作用的地方。

有时,包含一个或两个子查询的查询实际上比单独运行几个查询的时间效率更低。

我的建议是测试一下。获取一个查询,获取所需的所有数据,查看执行所需的时间。为其他五个查询计算时间并查看它们合并的时间。如果它几乎完全相同,请将输出粘贴到一个数组中,这样可以提高效率,因为不必频繁连接到数据库本身。

但是,如果组合查询返回数据需要更长时间(例如,它可能会导致全表扫描而不是使用索引),那么请坚持使用单个查询。

最后,如果您要反复使用相同的数据 - 数组或对象将每次赢得,因为访问它会快得多而不是从数据库中获取它。

答案 1 :(得分:4)

好的 - 我做了一些基准测试,并且惊讶地发现,将事物放入数组而不是使用单个查询,平均而言是10-15%SLOWER。

我认为之所以这样做是因为,即使我过滤掉了“不常见”的元素,也不可避免地总会出现未使用的元素。

通过个人查询,我只能得到我需要的内容,而且查询非常简单,我认为我最好坚持使用该方法。

这对我有用,当然在其他情况下,个别查询更复杂,我认为将数据存储在数组中的方法会更有效。

答案 2 :(得分:3)

同意每个人在这里说的话......这都与数字有关。

一些额外提示:

  1. 尝试创建一个保持所需最小值的单个内存数组。这意味着要删除大部分明显的裁员。

  2. 在性能关键环境中存在针对这些问题的标准方法,例如使用带有mysql的memcached。它有点矫枉过正,但这基本上可以让你分配一些外部内存并在那里缓存你的查询。由于您选择了要分配的内存量,因此可以根据系统的内存量进行规划。

  3. 玩这些数字吧。尝试使用单独的查询(这是最简单的方法)并强调您的PHP脚本(比如从命令行调用数百次)。测量这需要多长时间,看看实际上有多大的性能损失。从我个人的经验来看,我通常会将所有内容都缓存在内存中,然后有一天数据变得太大,我的内存耗尽。然后我将所有内容拆分为单独的查询以节省内存,并且首先看到性能影响并不是那么糟糕:)

答案 3 :(得分:1)

我和Fluffeh在一起:查看其他选项(连接,子查询,确保您的索引反映数据的相关性 - 但不要过度索引和测试) 。很可能你会在某个时刻得到一个阵列,所以这里有一点性能提示,与你的预期相反,像

这样的东西
$all = $stmt->fetchAll(PDO::FETCH_ASSOC);

比内存效率更低:

$all = array();//or $all = []; in php 5.4
while($row = $stmt->fetch(PDO::FETCH_ASSOC);
{
    $all[] = $row['lang_string '];
}

更重要的是:您可以在获取数据时检查冗余数据。

答案 4 :(得分:1)

我的回答是在两者之间做点什么。检索短于特定长度(例如,100个字符)的lang_id的所有字符串。较短的文本字符串比较长的文本字符串更有可能在多个地方使用。在get_lang_string()中缓存静态关联数组中的条目。如果找不到某个项目,则通过查询检索它。

答案 5 :(得分:0)

我目前正处于我site/application的位置,我不得不踩刹车并仔细考虑速度。我认为提到的这些速度测试应该将服务器上的流量视为影响结果的重要变量。如果要将数据放入javascript数据结构并在客户端计算机上进行处理,则处理时间应更加规则。如果你通过php(例如)通过mysql请求大量数据,这就需要在一台机器/服务器上而不是传播它。随着流量的增长,您不得不与许多用户共享服务器资源,我认为这是让JavaScript做更多事情的地方,这将减轻服务器的负担。您还可以通过localstorage.setItem(); / localstorage.getItem();将数据存储在本地计算机中(大多数浏览器每个域大约有5mb的空间)。如果数据库中的数据不经常更改,那么您可以将其存储到客户端,然后只需检查“启动”数据。如果它仍然在日期/有效。

这是我在使用和使用帐户1年后发布的第一条评论,所以我可能需要对我的漫无边际进行微调 - 只是表达了我目前的想法。