memcached可用于减少这些SELECT *查询的负载

时间:2013-06-22 00:19:05

标签: php mysql apache memcached

我有很多用户在apache服务器上轮询我的php脚本,他们运行的mysql查询是

"SELECT * FROM `table` WHERE `id`>'example number'

其中示例编号因用户而异,但具有已知的下限,每10分钟更新一次。

每个用户每秒轮询两次服务器。

可以使用memcache吗?用户显示最新的信息并不是至关重要的,如果它落后一秒,那就没问题了。

该站点在高峰时段有200个并发用户。这是非常低效的,并且耗费了大量资源。

3 个答案:

答案 0 :(得分:1)

为了给出准确答案,我需要更多信息

  1. 查询是否提取个性化信息。
  2. 轮询请求是否与请求一起出现“示例号”。
  3. 查看您构建问题的方式,似乎用户不会轮询任何个性化信息。所以我假设'示例号'也是轮询请求的一部分。

    我同意@roberttstephens和@Filippos Karapetis,你可以使用理想的解决方案

    1. Redis
    2. NoSQL
    3. 调整MySQL
    4. 内存缓存
    5. 但是,由于你们已经将应用程序放在野外,实施上述解决方案会产生成本,因此这些是我推荐的实用解决方案。

      1. 将表格的索引添加到相关列。 [检查/做的第一件事]
      2. 启用mysql查询缓存。
      3. 使用反向代理 - 例如:varnish。 [假设'示例号'作为请求的一部分]

        • 要在请求到达应用程序服务器之前交叉请求,以便MySQL查询,MemCache / Redis查找不会发生。
        • 确保您在响应中设置了特定的缓存标头,以便清漆缓存它。
        • 因此,在200个并发请求中,如果其中100个查询相同的数量,则清除获取命中。 [这与memcache也可以提供相同的优势]。
        • 实施方面,它在开发/测试工作方面的成本并不高。
        • 我知道这不是确切问题的答案。但我相信这可以解决你的问题。
      4. 如果'示例号'不作为请求的一部分,你必须从DB中获取它[通过查看用户表可能是..]然后@roberttstephens方法是要走的路。为了给你准确的图片,我稍微重构了一下代码。 `addServer('localhost',11211);

        $inputNumber = 12345;
        $cacheKey = "poll:".$inputNumber;
        
        $result = $m->get($cacheKey);
        if ($result) {
            return unserialize($result);
        }
        
        $sth = $dbh->prepare("SELECT column1, column2 FROM poll WHERE id = $inputNumber");
        $sth->execute();
        $poll_results = $sth->fetch(PDO::FETCH_OBJ);
        $m->set($cacheKey, serialize($poll_results));`
        

答案 1 :(得分:0)

在我看来,你在这里尝试使用错误的工具。

memcached是一个键/值存储,因此您可以非常快速地使用给定的一组键存储和检索多个值。但是,您似乎并不提前知道所需的密钥,因为您正在查找id GREATER THAN 一个数字而不是ID集合的所有记录。所以,在我看来,memcached不适合在你的场景中使用。

以下是您的选择:

选项1:继续使用MySQL并正确调整

如果你正确地调整它,MySQL会非常快。你可以:

  • 为每个表添加适当的索引
  • 使用prepared statements,因为用户使用不同的参数反复执行相同的查询,因此可以帮助您提高性能。
  • 使用查询缓存

    这里有a guide提供有关MySQL调优的一些提示,mysqltuner是一个Perl脚本,可以指导您完成优化MySQL数据库所需的选项。

选项2:使用更高级的键值存储

memcached还有其他选择,其中最着名的是redis。 redis确实允许更多的灵活性,但它比memcached更复杂。对于您的方案,您可以使用redis zrange命令检索所需的结果 - 查看可用的redis commands以获取更多信息。

选项3:使用文档存储NoSQL数据库

您可以使用文档存储NoSQL数据库,其中最着名的示例是MongoDB

您可以在MongoDB中使用更复杂的查询(例如,使用运算符,比如“大于”,您需要的),而不是在memcached中。 Here's an example of如何使用运算符搜索mongo集合中的结果(请参阅示例2)。

有关详细信息,请查看PHP MongoDB手册。

此外,this SO question是关于文档存储NoSQL数据库的有趣读物。

答案 2 :(得分:0)

绝对可以使用memcached来缓存结果。你可以用更少的努力在mysql中创建一个缓存表。

在任何一种情况下,您都需要为缓存创建一个id,并根据该ID检索结果。你可以使用类似entity_name:entity_id或namespace:entity_name:entity_id,或任何适合你的东西。

请记住,memcached是服务器上运行的另一项服务。您必须安装它,将其设置为在重新启动时启动(或者至少应),分配内存等。您还需要php-memcached。

话虽如此,请查看memcached上的php文档。 http://php.net/manual/en/memcached.set.php。假设您的民意调查ID是12345,您可以像这样使用memcached。

<?php
// Get your results however you normally would.

$sth = $dbh->prepare("SELECT column1, column2 FROM poll WHERE id = 12345");
$sth->execute();
$poll_results = $sth->fetch(PDO::FETCH_OBJ);

// Set up memcached. It should obviously be installed, configured, and running by now.
$m = new Memcached();
$m->addServer('localhost', 11211);

$m->set('poll:12345', serialize($poll_results));

此示例没有任何错误检查或任何内容,但这应解释如何执行此操作。我现在也没有运行php,mysql或memcached实例,因此上面的内容尚未经过测试。