11

我有一个基于 PHP/MySQL 的 Web 应用程序,它通过一个名为 , 和字段的 MySQL 表来language_strings支持string_id国际化lang_idlang_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 个链接文本,它们都调用了这个函数。

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

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

4

6 回答 6

8

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

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

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

我的建议是测试一下。一起获取一个查询,获取你需要的所有数据,看看执行需要多长时间。对其他五个查询中的每一个进行计时,看看它们合并需要多长时间。如果它几乎相同,请将输出粘贴到一个数组中,这样会更有效,因为不必频繁连接到数据库本身。

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

最后,如果您要一遍又一遍地使用相同的数据 - 数组或对象每次都会胜出,因为访问它比从数据库中获取它要快得多。

于 2012-08-21T08:56:50.727 回答
4

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

我认为这样做的原因是,即使我过滤掉了“不常见”的元素,不可避免地总会有一些未使用的元素作为理所当然的事情。

对于个人查询,我只会得到我需要的东西,而且由于查询非常简单,我认为我最好坚持使用这种方法。

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

于 2012-08-21T13:05:50.673 回答
3

同意每个人在这里所说的......这都是关于数字的。

一些额外的提示:

  1. 尝试创建一个存储您需要的最小值的单个内存阵列。这意味着删除大部分明显的冗余。

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

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

于 2012-08-21T09:06:00.253 回答
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 '];
}

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

于 2012-08-21T09:19:39.263 回答
1

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

于 2012-08-21T09:50:24.470 回答
0

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

这是我在拥有并使用该帐户 1 年后发表的第一条评论,因此我可能需要微调我的漫无边际 - 只是表达我目前的想法。

于 2014-05-20T13:15:41.990 回答