Sphinx
est un moteur de recherche full-text
On peut l'interroger au travers de son api, SphinxQL, en ligne de commande ou avec l'engine MySql SphinxSE
J'utilise MySqlSE;
SELECT * from INFORMATION_SCHEMA.ENGINES;
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
------ ------- --------------------------- ------------ ------ ----------
...
SPHINX YES Sphinx storage engine 0.9.9 NO NO NO
La question du jour était : Y a-t-il un moyen de connaître le nombre total de résultats quand on utilise un limit ?
En Mysql simple, il y a SQL_CALC_FOUND_ROWS
mysql> SELECT SQL_CALC_FOUND_ROWS *
-> FROM tbl_name
-> WHERE id > 100 LIMIT 10;
mysql> SELECT FOUND_ROWS();
Le second SELECT retourne un nombre indiquant combien de lignes le premier SELECT aurait retourné s'il n'avait pas été écrit avec une clause LIMIT.
Mais avec avec SPHINX
En testant sur ma table tbl_name_sphinx qui contient 2410 rows.
select SQL_CALC_FOUND_ROWS * from tbl_name_sphinx WHERE query='' LIMIT 10;
SELECT FOUND_ROWS();
Résultat
FOUND_ROWS()
------------
20
20 parce que c'est la valeur par défaut du limit de sphinx
# limit - amount of matches to retrieve from result set, default is 20;
(ref)
En effet si je force ce limit à 10
select SQL_CALC_FOUND_ROWS *
from tbl_name_sphinx
WHERE query=';limit=10';
SELECT FOUND_ROWS();
Résultat
FOUND_ROWS() -> 10
Pourquoi ? parce que c'est sphinx qui fait la vraie recherche et remonte son résultat à MySql
Donc quand je fait
select SQL_CALC_FOUND_ROWS *
from tbl_name_sphinx
WHERE query=';limit=1000'
LIMIT 10;
Je reçois 10 résultats sur 2410 réels et sur les 1000 que sphinx a remonté
Donc
SELECT FOUND_ROWS(); -> affiche 1000 et pas 2410.
Donc je vais monter mon limit à 1000000.
Gloups, je viens de demander à Sphinx de me préparer en résultat de 100K rows, tout renvoyer à mysql dans une table temporaire qui me retournera uniquement les 10 premiers.... Fameux gaspillage
Quand on sait que sphinx ne me retourne que les id et que donc il faut faire un join avec la table de données, ca fait mal.
la solution
SHOW ENGINE SPHINX STATUS;
On oublie le 'SQL_CALC_FOUND_ROWS'
Et on remplace FOUND_ROWS() par SHOW ENGINE SPHINX STATUS;
On remet le limit 10 au niveau de sphinx;
select *
from tbl_name_sphinx
WHERE query=';limit=10';
SHOW ENGINE SPHINX STATUS;
Type Name Status
------ ------ -------------------------------------------------
SPHINX stats total: 1000, total found: 2410, time: 0, words: 0
Bingo j'ai mon info,
planquée dans une "chaine" mais je l'ai.
re bingo
SHOW STATUS LIKE 'sphinx_%';
Mais je préfère INFORMATION_SCHEMA.
SELECT *
from information_schema.GLOBAL_STATUS
WHERE VARIABLE_NAME like 'SPHINX%';
VARIABLE_NAME VARIABLE_VALUE
------------------ --------------
SPHINX_ERROR 208409
SPHINX_TIME 0
SPHINX_TOTAL 1000
SPHINX_TOTAL_FOUND 2410
SPHINX_WORD_COUNT 0
SPHINX_WORDS
Et je suis un heureux.
Si vous êtes intéressés par Sphinx, voici un bon article pour l'installer.
Si vous vous êtes déjà intéressé à Zend_Search_Lucene, (bien décrit ici) il me semble avoir que celui-ci peut utiliser Sphinx comme backend. je corrigerai si je retrouve la source.