Мы используем индексы 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'
Если я скопирую / вставлю запрос в клиент CLI mysql, нет проблем:
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
является экземпляром класса Connection из http://foolcode.github.io/SphinxQL-Query-Builder/, но мы работаем с подключением mysqli напрямую, используя $conn->getConnection()
:
$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();
}
Я пытался использовать multiQuery()
функция из класса соединения SphinxQL Query Builder с теми же результатами.
Сообщение об ошибке, утверждающее, что точка с запятой является неожиданной, кажется мне самой странной частью. Если он хочет $ 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
полученное сообщение об ошибке от сервера searchd, потому что оно не ожидать нескольких команд, связанных с;
Запрос работает в CLI, потому что mysql клиент сам разбивает его на отдельные запросы и отправляет их по одному на сервер (см. разделитель).
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, только для запросов — см. Комментарий к основному вопросу.
Так что в это время (версия 2.2.7), документы (http://sphinxsearch.com/docs/current/sphinxql-multi-queries.html) указывают на то, что поддержка нескольких запросов предназначена только для запросов SELECT, SHOW WARNINGS, SHOW STATUS и SHOW META. Это объясняет, почему sphinx ожидает конца запроса, а не ‘;’ для запросов ОБНОВЛЕНИЕ.
Барри предложил мне на форумах сфинксов (http://sphinxsearch.com/forum/view.html?id=13201) использовать UpdateAttributes API sphinx (http://sphinxsearch.com/docs/current.html#api-func-updateatttributes) функция для обработки массовых обновлений. Это сработало очень хорошо. Мы наблюдаем 5 000 обновлений в секунду для двух разных индексов (одни и те же данные индексируются двумя разными способами) в одном потоке нашего оборудования EC2 (r3.xlarge, индексы на эфемерном SSD).