【问题标题】:multi_query not working in mysqli to update realtime sphinx index via sphinxqlmulti_query 在 mysqli 中无法通过 sphinxql 更新实时 sphinx 索引
【发布时间】:2015-01-21 13:52:02
【问题描述】:

我们正在使用 Sphinx 实时索引并通过 PHP 的 mysqli 驱动程序与它们对话。单个查询工作正常,但我们正在尝试使用 multi_query 实现批量更新过程。

查询如下所示:

UPDATE rt SET rank = 1 WHERE id = 881523;
UPDATE rt SET rank = 2 WHERE id = 881727;
UPDATE rt ...

(这是在用分号内爆之后,为了便于阅读添加了换行符)

我们得到的错误是:

sphinxql: syntax error, unexpected ';', expecting $end near ';UPDATE rt SET rank = 2 WHERE id = 881727'

如果我将查询复制/粘贴到 mysql CLI 客户端,没问题:

mysql> UPDATE rt SET rank = 1 WHERE id = 881523;UPDATE rt SET rank = 2 WHERE id = 882884;UPDATE rt SET rank = 3 WHERE id = 881727;
Query OK, 1 row affected (0.01 sec)

Query OK, 1 row affected (0.01 sec)

Query OK, 1 row affected (0.01 sec)

这是 PHP 代码。 $conn 是来自 http://foolcode.github.io/SphinxQL-Query-Builder/ 的 Connection 类的一个实例,但我们正在使用 $conn->getConnection() 直接处理底层 mysqli 连接:

$query = implode(';', $queries);
if($conn->getConnection()->multi_query($query)) {
        do { }
        while($conn->getConnection()->next_result());
}
if($conn->getConnection()->error) {
        error_log("query: " . $query);
        error_log($conn->getConnection()->error);
        die();
}

我尝试使用 SphinxQL 查询生成器连接类中的 multiQuery() 函数,结果相同。

声称分号是意外的错误消息对我来说似乎是最奇怪的部分。如果它想要 $end,这是否意味着它不支持多个查询?如果它愿意通过 mysql 客户端进行相同的查询,为什么不呢?

$php -v
PHP 5.5.20 (cli) (built: Dec 29 2014 18:02:29) 
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2014, by Zend Technologies

【问题讨论】:

  • 我看到你使用了implode(),但是在 imploding 之后你是否在$query 的末尾添加了; 来完成 SQL 字符串?
  • 我试过有无,两种方式都没有区别。我注意到很多地方的示例代码都没有在最后添加一个,所以我认为它是可选的。
  • 您是否考虑过使用准备好的语句并简单地迭代更新?我的猜测是这样你会获得更好的性能,因为查询不需要每次都重新规划。
  • 记住这是 sphinx(尽管这个问题被 mysql 标记) - sphinx 不支持协议准备语句。 (仅限客户端模拟的)
  • 找到这个页面:sphinxsearch.com/docs/current/sphinxql-multi-queries.html。似乎表明虽然某些类型的查询支持它,但 UPDATE 不是其中之一。

标签: php mysql mysqli sphinx sphinxql


【解决方案1】:

您收到的错误消息来自 searchd 服务器,因为它期望多个命令与 ;

查询在 CLI 中工作,因为 mysql client 本身将其拆分为单独的查询,并将它们一一发送到服务器(请参阅分隔符选项)。 https://mariadb.com/kb/en/mariadb/documentation/clients-and-utilities/mysql-client/delimiters-in-the-mysql-client/

mysqli,有类似的查询功能 http://php.net/manual/en/mysqli.multi-query.php 这是硬编码使用的;显然。结果证明 sphinx 不支持它用于 UPDATE 查询,仅用于查询 - 请参阅对主要问题的评论。

【讨论】:

  • 我不确定我是否理解您试图就 mysqli 的多查询功能提出的观点。您是说它能够自行拆分查询并一次发送一个查询,还是只是重申它无法为 sphinx 提供预期的结果?
  • 假设 sphinx 不能处理分号分隔的查询,这似乎是这种情况,有没有办法将 mysqli 置于可以快速处理一堆查询的模式无需等待每次往返?如果我们一一执行这些查询,则需要很长时间。
  • 我主要是解释 CLI 为何有效。但也说 mysqli 的 multi_query 应该工作。我无法解释为什么它对你不起作用。但是话又说回来,我只使用 multi_query 来执行多个选择语句,从不进行多次更新
【解决方案2】:

所以目前(2.2.7 版),文档 (http://sphinxsearch.com/docs/current/sphinxql-multi-queries.html) 表明多查询支持仅适用于 SELECT、SHOW WARNINGS、SHOW STATUS 和 SHOW META 查询。这解释了为什么 sphinx 期望查询结束而不是 ';'用于 UPDATE 查询。

Barry 在 sphinx 论坛 (http://sphinxsearch.com/forum/view.html?id=13201) 上向我建议使用 sphinx API 的 UpdateAttributes (http://sphinxsearch.com/docs/current.html#api-func-updateatttributes) 函数来处理批量更新。这工作得很好。我们在 EC2 硬件(r3.xlarge,临时 SSD 上的索引)的单个线程上看到两个不同索引(相同数据以两种不同方式索引)的每秒 5k 更新。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多