sphinx 0.9.9
Sphinx 全文检索服务器 0.9.9 参考手册
文档版本:v0.9
刘光照 2009-11-23
目录
内容目录
1.简介 6
1.1.什么是Sphinx 6
1.2.Sphinx特性 6
1.3.如何获得Sphinx 7
1.4.许可协议 7
1.5.作者和贡献者 7
1.6.历史 8
2.安装 8
2.1.支持的操作系统 8
2.2.依赖的工具 9
2.3.安装Sphinx 9
2.4.Installing Sphinx on Windows 10
2.5.已知的问题和解决办法 11
2.6.Sphinx 快速入门教程 11
3.建立索引 12
3.1.数据源 12
3.2.属性 13
3.3.多值属性MVA (multi-valued attributes) 15
3.4.索引 15
3.5.数据源的限制 16
3.6.字符集、大小写转换和转换表 16
3.7.SQL数据源(MySQL, PostgreSQL) 17
3.8.Xmlpipe数据源 18
3.9.xmlpipe2数据源 19
3.10.实时索引更新 21
3.11.索引合并 23
4.搜索 24
4.1.匹配模式 24
4.2.布尔查询 25
4.3.扩展查询 25
4.4.权值计算 29
4.5.排序模式 30
4.6.结果分组(聚类) 35
4.7.分布式搜索 36
4.8.Searchd日志格式 38
4.9.MySQL 协议支持和SphinxQL 39
5.命令行工具手册 47
5.1.search命令参考 47
6.API参考手册 52
6.1.通用API函数 52
6.1.1.GetLastError 52
6.1.2.GetLastWarning 53
6.1.3.SetServer 53
6.1.4.SetRetries 53
6.1.5.SetConnectTimeout 53
6.1.6.SetArrayResult 54
6.1.7.IsConnectError 54
6.2.通用搜索设置 55
6.2.1.SetLimits 55
6.2.2.SetMaxQueryTime 55
6.2.3.SetOverride 56
6.2.4.SetSelect 56
6.3.全文搜索设置 58
6.3.1.SetMatchMode 58
6.3.2.SetRankingMode 58
6.3.3.SetSortMode 59
6.3.4.SetWeights 59
6.3.5.SetFieldWeights 59
6.3.6.SetIndexWeights 60
6.4.结果集过滤设置 60
6.4.1.SetIDRange 60
6.4.2.SetFilter 61
6.4.3.SetFilterRange 61
6.4.4.SetFilterFloatRange 61
6.4.5.SetGeoAnchor 61
6.5.GROUP BY 设置 62
6.5.1.SetGroupBy 62
6.5.2.SetGroupDistinct 62
6.6.Querying 63
6.6.1.Query 63
6.6.2.AddQuery 64
6.6.3.RunQueries 66
6.6.4.ResetFilters 66
6.6.5.ResetGroupBy 67
6.7.额外的功能 67
6.7.1.BuildExcerpts 67
6.7.2.UpdateAttributes 68
6.7.3.BuildKeywords 68
6.7.4.EscapingString 69
6.7.5.Status 69
6.8.持久连接(长连接) 70
6.8.1.Open 70
6.8.2.Close 70
7.MySQL存储引擎(SphinxSE) 70
8.报告 bugs 70
9.sphinx.conf选项参考 70
9.1.Data Source配置选项 70
9.1.1.type 70
9.2.索引文件配置选项 71
9.2.1.path 71
9.3.indexer索引器程序配置选项 71
9.3.1.mem_limit 71
9.3.2.max_iops 72
9.3.3.max_iosize 72
9.3.4.max_xmlpipe2_field 73
9.3.5.write_buffer 73
9.4.Searchd程序配置选项 73
10.Sphinx版本历史 73
11.错误代号列表 73
11.1.Indexer 73
11.2.searchd 74
12.常见问题说明 74
Sphinx 是一个在GPLv2 下发布的一个全文检索引擎,商业授权(例如, 嵌入到其他程序中)需要联系我们(Sphinxsearch.com)以获得商业授权。
一般而言,Sphinx是一个独立的搜索引擎,意图为其他应用提供高速、低空间占用、高结果相关度的全文搜索功能。Sphinx可以非常容易的与SQL数据库和脚本语言集成。
当前系统内置MySQL和PostgreSQL 数据库数据源的支持,也支持从标准输入读取特定格式的XML数据。通过修改源代码,用户可以自行增加新的数据源(例如:其他类型的DBMS
的原生支持)。
搜索API支持PHP、Python、Perl、Rudy和Java,并且也可以用作MySQL存储引擎。搜索
API非常简单,可以在若干个小时之内移植到新的语言上。
Sphinx 是SQL Phrase Index的缩写,但不幸的和CMU的Sphinx项目重名。
高速的建立索引(在当代CPU上,峰值性能可达到10 MB/秒);
高性能的搜索(在2 – 4GB 的文本数据上,平均每次检索响应时间小于0.1秒);
可处理海量数据(目前已知可以处理超过100 GB的文本数据, 在单一CPU的系统上可
处理100 M 文档);
提供了优秀的相关度算法,基于短语相似度和统计(BM25)的复合Ranking方法;
支持分布式搜索;
provides document exceprts generation;
可作为MySQL的存储引擎提供搜索服务;
支持布尔、短语、词语相似度等多种检索模式;
文档支持多个全文检索字段(最大不超过32个);
文档支持多个额外的属性信息(例如:分组信息,时间戳等);
停止词查询;
支持单一字节编码和UTF-8编码;
原生的MySQL支持(同时支持MyISAM 和InnoDB );
原生的PostgreSQL 支持.
Sphinx 可以从官方网站http://www.sphinxsearch.com/ 下载。
目前,Sphinx的发布包包括如下软件:
indexer: 用于创建全文索引;
search: 一个简单的命令行(CLI) 的测试程序,用于测试全文索引;
searchd: 一个守护进程,其他软件可以通过这个守护进程进行全文检索;
sphinxapi: 一系列searchd 的客户端API 库,用于流行的Web脚本开发语言(PHP,。 Python, Perl, Ruby, Java)。
spelldump: 一个简单的命令行工具,用于从ispell或MySpell(OpenOffice带的)格式的字典中抽取词条,自定义你的索引,与词汇工具一起用。
indextool: 一个显示索引调试信息的工具,在0.9.9-rc2加入。
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See COPYING file for details.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
If you don't want to be bound by GNU GPL terms (for instance, if you would like to embed Sphinx in your software, but would not like to disclose its source code), please contact the author to obtain a commercial license.
作者
Sphinx 的最初作者和目前的主要开发人员:
Andrew Aksyonoff, <shodan(at)shodan.ru>
贡献者
为Sphinx的开发出过力的人员和他们的贡献如下(以下排名不分先后):
Robert "coredev" Bengtsson (Sweden), initial version of PostgreSQL data source;
Len Kranendonk, Perl API
Dmytro Shteflyuk, Ruby API
此外,还有许多人提出了宝贵的想法、错误报告以及修正。在此一并致谢。
Sphinx 的开发工作可以上溯到2001年,当时作者试图为一个数据库驱动的网站寻找一个可
接受的搜索的解决方案,但是当时没有任何方案能够满足要求。事实上,主要是如下问题:
搜索质量(例如:有效的相关度算法)
单纯的统计学方法的效果非常糟糕,特别是在大量的短篇文档的集合上,例如:论坛、博客等等。
搜索速度
特别是当搜索的短语包括“停止词”时,表现的尤其明显,例如:"to be or not to be"
建立索引时,可控的磁盘和CPU消耗
在虚拟主机的环境下,这一点的重要性要超过对索引构造速度的要求
年复一年,其他的解决方案有了很多改进,但是,我个人认为仍然没有一种解决方案足够的好,能让我将搜索平台迁移过去。
去年,Sphinx的用户给了我很多正面的反馈,因此,显而易见的,Sphinx的开发过程将会继
续(也许将持续到世界末日)。
在绝大多数现代的Unix类操作系统上,只需要一个C++编译器就可以编译并运行Sphinx,而不需要对源码进行任何改动。
目前,Sphinx可以在以下系统上运行:
Linux 2.4.x, 2.6.x (包括各种发行版)
Windows 2000, XP
FreeBSD 4.x, 5.x, 6.x
NetBSD 1.6, 3.0
Solaris 9, 11
Mac OS X
支持的CPU种类包括X86, X86-64, SPARC64。
我希望Sphinx也能够在其他的Unix平台上工作,如果你运行Sphinx使用的操作系统不在上面的名单中,请告诉我。
目前的阶段,Sphinx的Windows版可用于测试和调试,但不建议用于生产系统。最突出的两个问题是:1)缺少并发查询的支持;2)缺少索引数据热切换的支持。虽然目前已经有成功的生产环境克服了这两个问题,仍然不推荐在Windows下运行Sphinx提供高强度的搜索服务。
在UNIX平台上,你需要以下的工具用来编译和安装Sphinx:
C++编译器。GNU gcc 就能够干这个活。
make程序。GNU make 就能够干这个活。
在Windows平台上,你需要Microsoft Visual C/C++ Studio .NET 2003 or 2005。其他的编译器/开发环境也许也能搞定这件事,但你可能需要自己手工制作他们所需的Makefile或者工程文件。
1. 将你下载的tar包解压,并进入sphinx 子目录:
$ tar xzvf sphinx-0.9.7.tar.gz
$ cd sphinx
2. 运行configuration 程序:
$ ./configure
configure程序有很多运行选项。完整的列表可以通过使用 --help 开关得到。最重要的如下:
--prefix, 定义将Sphinx安装到何处;
--with-mysql, 当自动检测失败时,指出在那里能找到MySQL 头文件和库文件;
--with-pgsql, 指出在那里能找到PostgreSQL头文件和库文件。
3. 编译二进制程序:
$ make
4. 按照二进制程序到你选好的目录下:(在*nix系统默认安装到 /usr/local/bin/ ,但是可以通过configure 的--prefix参数指定其他安装路径)
$ make install
Installing Sphinx on a Windows server is often easier than installing on a Linux environment; unless you are preparing code patches, you can use the pre-compiled binary files from the Downloads area on the website.
Extract everything from the .zip file you have downloaded - sphinx-0.9.8-win32.zip (or sphinx-0.9.8-win32-pgsql.zip if you need PostgresSQL support as well.) You can use Windows Explorer in Windows XP and up to extract the files, or a freeware package like 7Zip to open the archive.
For the remainder of this guide, we will assume that the folders are unzipped into C:\Sphinx, such that searchd.exe can be found in C:\Sphinx\bin\searchd.exe. If you decide to use any different location for the folders or configuration file, please change it accordingly.
Install the searchd system as a Windows service:
C:\Sphinx> C:\Sphinx\searchd --install --config C:\Sphinx\sphinx.conf --servicename SphinxSearch
The searchd service will now be listed in the Services panel within the Management Console, available from Administrative Tools. It will not have been started, as you will need to configure it and build your indexes with indexer before starting the service. A guide to do this can be found under Quick tour.
如果configure 程序没有找到MySQL 的头文件和库文件,请试图检查 mysql-devel 这
个包是否安装了。在有些系统上,默认安装包括这个包。
如果make程序给出如下错误提示,
/bin/sh: g++: command not found
make[1]: *** [libsphinx_a-sphinx.o] Error 127
请检查gcc-c++ 这个包是否安装了。
如果你在编译时得到如下错误
sphinx.cpp:67: error: invalid application of `sizeof' to
incomplete type `Private::SizeError<false>'
这意味着某些编译时的类型检查失败了,一个最有可能的原因是在你的系统上类型off_t的长度小于64bit。一个快速的修复手段是,你可以修改sphinx.h ,将在定义类型SphOffset_t处,将off_t 替换成DWORD,需要注意,这种改动将使你的全文索引文件不能超过2GB。即便这种修改有用,也请汇报这一问题,在汇报中请包括具体的错误信息以及操作系统编译器的配置情况。这样,我可能能够在下一个版本中解决这一问题。
如何你遇到了其他的任何问题,或者前面的建议对你没有帮助,别犹豫,请立刻联系我。
以下所有的例子都假设你将sphinx安装在目录 /usr/local/sphinx 中了,那么searchd的路径为/usr/local/bin/searchd。
为了使用Sphinx,你需要:
1. 创建配置文件
缺省的配置文件名为sphinx.conf。全部的Sphinx提供的程序默认都在当前工作的目录下寻找该文件。
由configure 程序生成的示例配置文件sphinx.conf.dist 中包括全部选项的注释,复制并编辑这个文件使之适用于你的具体情况:
$ cd /usr/local/sphinx/etc
$ cp sphinx.conf.dist sphinx.conf
$ vi sphinx.conf
在示例配置文件中,将试图对MySQL数据库test中的documents 表建立索引;
因此在这里还提供了example.sql 用于给测试表增加数据用于测试:
$ mysql -u test < /usr/local/sphinx/etc/example.sql
2. 运行indexer 创建你的全文索引:
$ cd /usr/local/sphinx/etc
$ /usr/local/sphinx/bin/indexer
3. 检索你新创建的索引!
你可以使用search实用程序可以从命令行对索引进行检索:
$ cd /usr/local/sphinx/etc
$ /usr/local/sphinx/bin/search test
如果要从PHP脚本检索索引,你需要:
1. 运行守护进程searchd,PHP脚本需要连接到searchd上进行检索 :
$ cd /usr/local/sphinx/etc
$ /usr/local/sphinx/bin/searchd
2. 运行PHP API 附带的test 脚本(运行之前请确认searchd守护进程已启动):
$ cd sphinx/api
$ php test.php test
3. 将API文件(位于api/sphinxapi.php) 包含进你自己的脚本,开始编程。
搜索愉快!
索引的数据可以来自各种各样不同的来源:SQL数据库、纯文本、HTML文件、邮件等等。从Sphinx的视角看,索引数据是一个结构化的文档的集合,其中每个文档是字段的集合,这和SQL数据库的视角有所不同,在那里,每一行代表一个文档,每一列代表一个字段。
由于数据来源的不同,需要不同的代码来获取数据、处理数据以供Sphinx进行索引的建立。这种代码被称之为数据源驱动程序(简称:驱动或数据源)。
在本文撰写时,Sphinx中包括MySQL和PostgreSQL数据源的驱动程序,这些驱动使用数据库系统提供的C/C++原生接口连接到数据库服务器并获取数据。此外,Sphinx还提供了额外的被成为xmlpipe的数据源驱动,该驱动运行某个具体的命令,并从该命令的输出中读入数据。数据的格式在 3.8, “xmlpipe 数据源” 中有介绍。
如果确有必要,一个索引的数据可以来自多个数据源。这些数据将严格按照配置文件中定义的顺序进行处理。所有从这些数据源获取到的文档将被合并,共同产生一个索引,如同他们来源于同一个数据源一样。
属性是附加在每个文档上的额外的信息(值),可以在搜索的时候用于过滤和排序。
搜索结果通常不仅仅是进行文档的匹配和相关度的排序,经常还需要根据其他与文档相关联
的值,对结果进行额外的处理。例如,用户可能需要对新闻检索结果依次按日期和相关度排
序,检索特定价格范围内的产品,检索某些特定用户的blog日志,或者将检索结果按月分
组。为了高效地完成上述工作,Sphinx允许给文档附加一些额外的值,并把这些值存储在全
文索引中,以便在对全文匹配结果进行过滤、排序或分组时使用。
属性与字段不同的是它不做全文索引。它们存储在索引中,但不能像全文检索一样搜索它们,如果这么做会导致错误结果。Attributes, unlike the fields, are not full-text indexed. They are stored in the index, but it is not possible to search them as full-text, and attempting to do so results in an error.
For example, it is impossible to use the extended matching mode expression @column 1 to match documents where column is 1, if column is an attribute, and this is still true even if the numeric digits are normally indexed.
属性可用于过滤,也就是说,确定返回的行,就像排序或结果集分组一样。可以完全基于属性排序结果集,并忽略搜索的关联工具。另外,属性还会从search守护进程返回,但索引的文本不会返回。Attributes can be used for filtering, though, to restrict returned rows, as well as sorting or result grouping; it is entirely possible to sort results purely based on attributes, and ignore the search relevance tools. Additionally, attributes are returned from the search daemon, while the indexed text is not.
论坛帖子表是一个很好的例子。假设只有帖子的标题和内容这两个字段需要全文检索,但是有时检索结果需要被限制在某个特定的作者的帖子或者属于某个子论坛的帖子中(也就是说,只检索在SQL表的author_id和forum_id这两个列上有特定值的那些行),或者需要按
post_date列对匹配的结果排序,或者根据post_date列对帖子按月份分组,并对每组中的帖
子计数。
为实现这些功能,可以将上述各列(除了标题和内容列)作为属性做索引,之后即可使用API调用来设置过滤、排序和分组。以下是一个例子:
示例:sphinx.conf片断:
...
sql_query = SELECT id, title, content, \
author_id, forum_id, post_date FROM my_forum_posts
sql_attr_uint = author_id
sql_attr_uint = forum_id
sql_attr_timestamp = post_datepp
...
示例: 应用程序代码 (PHP):
// only search posts by author whose ID is 123
$cl->SetFilter ( "author_id", array ( 123 ) );
// only search posts in sub-forums 1, 3 and 7
$cl->SetFilter ( "forum_id", array ( 1,3,7 ) );
// sort found posts by posting date in descending order
$cl->SetSortMode ( SPH_SORT_ATTR_DESC, "post_date" );
可以通过名字来指示特定的属性,并且这个名字是大小写无关的(注意:直到目前为止,
Sphinx还不支持中文作为属性的名称)。属性并不会被全文索引,他们只是按原封不动的存
储在索引文件中。目前支持的属性类型如下:
无符号整数(1-32位宽)
UNIX 时间戳(timestamps)
浮点值(32位,IEEE 754单精度)
字符串叙述 (尤其是计算出的整数值);
多值属性 MVA (multi-value attributes)(32位无符号整形值的变长序列).
由各个文档的全部的属性信息构成了一个集合,它也被称为文档信息docinfo),docinfo
可以按如下两种方式之一存储:
与全文索引数据分开存储(“外部存储”,在.spa文件中存储)
在全文索引数据中,每出现一次文档ID 就出现相应的文档信息(“内联存储”,在.spd文件中存储).
当采用外部存储方式时,searchd总是在RAM中保持一份.spa文件的拷贝(该文件包含所有文档的所有文档信息)。这是主要是为了提高性能,因为磁盘的随机访问太慢了。相反,内联存储并不需要任何额外的RAM,但代价是索引文件的体积大大地增加了;请注意,全部
属性值在文档ID出现的每一处都被复制了一份,而文档ID出现的次数恰是文档中不同关键
字的数目。仅当有一个很小的属性集、庞大的数据集和受限的RAM时,内联存储才是一个
可考虑的选择。在大多数情况下,外部存储可令建立索引和检索的效率都大幅提高。
检索时采用外部存储方式产生的的内存需求为 (1+number_of_attrs)*number_of_docs*4字节,也就是说,带有两个属性和一个时间戳的1千万篇文档会消耗(1+2+1)*10M*4 = 160 MB的RAM。这是每个检索的守护进程(daemon)消耗的量,而不是每次查询,searchd仅在启动时分配160MB的内存,读入数据并在不同的查询之间保持这些数据。子进程并不会对这些数据做额外的拷贝。
多值属性MVA (multi-valued attributes)是文档属性的一种重要的特例,MVA使得向文档附加一系列的值作为属性的想法成为可能。这对文章的tags,产品类别等等非常有用。MVA属性支持过滤和分组(但不支持分组排序)。
目前MVA列表项的值被限制为32位无符号整数。列表的长度不受限制,只要有足够的
RAM,任意个数的值都可以被附加到文档上(包含MVA值的.spm文件会被searchd预缓冲
到RAM中)。源数据既可以来自一个单独的查询,也可以来自文档属性,参考
sql_attr_multi 中的源类型。在第一种情况中,该查询须返回文档ID和MVA值的序对;而在
第二种情况中,该字段被分析为整型值。对于多值属性的输入数据的顺序没有任何限制,在
索引过程中这些值会自动按文档ID分组(而相同文档ID下的数据也会排序)。
在过滤过程中,MVA属性中的任何一个值满足过滤条件,则文档与过滤条件匹配(因此通过排他性过滤的文档不会包含任何被禁止的值)。按MVA属性分组时,一篇文档会被分到
与多个不同MVA值对应的多个组。例如,如果文档集只包含一篇文档,它有一个叫做tag
的MVA属性,该属性的值是5、7和11,那么按tag的分组操作会产生三个组,它们的
@count都是1,@groupby键值分别是5、7和11。还要注意,按MVA分组可能会导致结果
集中有重复的文档:因为每篇文文档可能属于不同的组,而且它可能在多个组中被选为最佳
结果,这会导致重复的ID。由于历史原因,PHP API对结果集的行进行按文档ID的有序
hash,因此用PHP API进行对MVA属性的分组操作时你还需要使用 SetArrayResult()。
为了快速地响应查询,Sphinx需要从文本数据中建立一种为查询做优化的特殊的数据结构。这种数据结构被称为索引(index);而建立索引的过程也叫做索引或建立索引(indexing)。
不同的索引类型是为不同的任务设计的。比如,基于磁盘的B-Tree存储结构的索引可以更新起来比较简单(容易向已有的索引插入新的文档),但是搜起来就相当慢。因此Sphinx
的程序架构允许实现多种不同类型的索引。
目前在Sphinx中实现的唯一一种索引类型是为最优化建立索引和检索的速度而设计的。随之而来的代价是更新索引相当的很慢。理论上讲,更新这种索引甚至可能比从头重建索引还要慢。不过大多数情况下这可以靠建立多个索引来解决索引更新慢的问题,细节请参考 节3.10, “ 实时索引更新 ”实现更多的索引类型支持,已列入计划,其中包括一种可以实时更新的类型。
每个配置文件都可以按需配置足够多的索引。indexer 工具可以将它们同时重新索引
(如果使用了--all选项)或者仅更新明确指出的一个。 Searchd工具会为所有被指明
的索引提供检索服务,而客户端可以在运行时指定使用那些索引进行检索。
Sphinx索引的源数据有一些限制,其中最重要的一条是:
所有文档的ID必须是唯一的无符号非零整数(根据Sphinx构建时的选项,可能是32位或64位)
如果不满足这个要求,各种糟糕的情况都可能发生。例如,Sphinx建立索引时可能在突然崩溃,或者由于冲突的文档ID而在索引结果中产生奇怪的结果。也可能,一只重达1000磅的大猩猩最后跳出你的电脑,向你扔木桶。我告诉你咯!
当建立索引时,Sphinx从指定的数据源获得文本文档,将文本分成词的集合,再对每个词做大小写转换,于是“Abc”,“ABC”和“abc”都被当作同一个词(word,或者更学究一点,
词项term)。
为了正确完成上述工作,Sphinx需要知道:
源文本是什么编码的
那些字符是字母,哪些不是
哪些字符需要被转换,以及被转换成什么
这些都可以用charset_type 和 charset_table 选项为每个索引单独配置。 charset_type 指定文档的编码是单字节的(SBCS)还是UTF-8的。charset_table 则指定了字母类字符到它们的大小写转换版本的对应表,没有在这张表中出现的字符被认为是非字母类字符,并且在建立索引和检索时被当作词的分割符来看待。
注意,尽管默认的转换表并不包含空格符 (ASCII 0x20, Unicode U+0020),但这么做是完全合法的。这在某些情况下可能有用,比如在对tag云构造索引的时候,这样一个用空格分开的词集就可以被当作一个单独的查询项了。
默认转换表目前包括英文和俄文字符。请您提交您为其他语言撰写的转换表!
对于所有的SQL驱动,建立索引的过程如下:
连接到数据库
执行预查询 (参见 节 8.1.9, “sql_query_pre ”) ,以便完成所有必须的初始设置,比如为MySQL连接设置编码
执行主查询(参见 节 8.1.10, “sql_query ”),其返回的的数据将被索引
执行后查询 (参见 节 8.1.19, “sql_query_post ”),以便完成所有必须的清理工作
关闭到数据库的连接
对短语进行排序 (或者学究一点, 索引类型相关的后处理)
再次建立到数据库的连接
执行后索引查询 (参见 节 8.1.20, “sql_query_post_index ”) ,以便完成所有最终的清理工作
再次关闭到数据库的连接
大多数参数是很直观的,例如数据库的用户名、主机、密码。不过,还有一些细节上的问题需要讨论。
分区查询
Sphinx需要通过主查询来获取全部的文档信息,一种简单的实现是将整个表的数据读入内存,但是这可能导致整个表被锁定并使得其他操作被阻止(例如:在MyISAM格式上的INSERT操作),同时,将浪费大量内存用于存储查询结果,诸如此类的问题吧。为了避免出现这种情况,Sphinx支持一种被称作“分区查询”的技术。首先,Sphinx从数据库中取出文档ID的最小值和最大值,将由最大值和最小值定义自然数区间分成若干份,一次获取数据,建立索引。现举例如下:
例 1. 使用分区查询的例子
# in sphinx.conf
sql_query_range = SELECT MIN(id),MAX(id) FROM documents
sql_range_step = 1000
sql_query = SELECT * FROM documents WHERE id>=$start AND id<=$end
如果这个表(documents)中,字段ID的最小值和最大值分别是1 和2345,则sql_query将执行3次:
1. 将$start 替换为1 ,并且将$end 替换为1000;
2. 将$start 替换为1001 ,并且将 $end 替换为2000;
3. 将$start 替换为2000 ,并且将 $end 替换为2345.
显然,这对于只有2000行的表,分区查询与整个读入没有太大区别,但是当表的规模扩大到千万级(特别是对于MyISAM格式的表),分区查询将提供一些帮助。
后查询(sql_post) vs. 索引后查询(sql_post_index)
后查询和索引后查询的区别在于,当Sphinx获取到全部文档数据后,立即执行后查询,但是构建索引的过程仍然可能因为某种原因失败。在另一方面,当索引后查询被执行时,可以理所当然的认为索引已经成功构造完了。因为构造索引可能是个漫长的过程,因此对与数据库的连接在执行后索引操作后被关闭,在执行索引后操作前被再次打开。
xmlpipe 数据源是处于让用户能够将现有数据嵌入Sphinx而无需开发新的数据源驱动的目的被设计和提供的。它将每篇文档限制为只能包括两个可全文索引的字段,以及只能包括两个属性。xmlpipe数据源已经被废弃,在 节 3.9, “xmlpipe2 数据源” 中描述了xmlpipe的替代品xmlpipe2数据源。对于新的数据,建议采用xmlpipe2。.
为了使用xmlpipe,需要将配置文件改为类似如下的样子:
source example_xmlpipe_source
{
type = xmlpipe
xmlpipe_command = perl /www/mysite.com/bin/sphinxpipe.pl
}
indexer 实用程序将要运行xmlpipe_command 所指定的命令,而后读取其向标准输出上
输出的数据,并对之进行解析并建立索引。严格的说,是Sphinx打开了一个与指定命令相
连的管道,并从这个管道读取数据。
indexer 实用程序假定在从标准输入读入的XML格式的数据中中存在一个或更多的文档。下面是一个包括两个文档的文档数据流的例子:
Example 2. XMLpipe 文档数据流
<document>
<id>123</id>
<group>45</group>
<timestamp>1132223498</timestamp>
<title>test title</title>
<body>
this is my document body
</body>
</document>
<document>
<id>124</id>
<group>46</group>
<timestamp>1132223498</timestamp>
<title>another test</title>
<body>
this is another document
</body>
</document>
遗留的xmlpipe的遗留的数据驱动使用内置的解析器来解析xml文档,这个解析器的速度非常快,但是并没有提供对XML格式完整支持。这个解析器需要文档中包括全部的字段,并
且严格按照例子中给出的格式给出,而且字段的出现顺序需要严格按照例子中给出的顺序。
仅有一个字段timestamp是可选的,它的缺省值为1。
xmlpipe2使你可以用另一种自定义的XML格式向Sphinx传输任意文本数据和属性数据。数据模式(即数据字段的集合或者属性集)可以由XML流本身指定,也可以在配置文件中数据源的配置部分中指定。
Xmlpipe2
在对xmlpipe2数据源做索引时,索引器运行指定的命令,打开一个连接前述命令标准输出的管道,并等待接受具有正确格式的XML数据流。以下是一个数据流的样本:
示例3 xmlpipe2文档流
<?xml version="1.0" encoding="utf-8"?>
<sphinx:docset>
<sphinx:schema>
<sphinx:field name="subject"/>
<sphinx:field name="content"/>
<sphinx:attr name="published" type="timestamp"/>
<sphinx:attr name="author_id" type="int" bits="16" default="1"/>
</sphinx:schema>
<sphinx:document id="1234">
<content>this is the main content <![CDATA[[and this <cdata> entry must be
handled properly by xml parser lib]]></content>
<published>1012325463</published>
<subject>note how field/attr tags can be in <b class="red">randomized</b>
order</subject>
<misc>some undeclared element</misc>
</sphinx:document>
<!-- ... more documents here ... -->
</sphinx:docset>
任意多的数据字段和属性都是允许的。数据字段和属性在同一文档元素中出现的先后顺序没有特别要求。。单一字段数据的最大长度有限制,超过2MB的数据会被截短到2MB(但这个限制可以在配置文件中数据源部分修改)
数据模式,即数据字段和属性的完整列表,必须在任何文档被分析之前就确定。这既可以在配置文件中用xmlpipe_field和xmlpipe_attr_xxx选项指定,也可以就在数据流中用
<sphinx:schema>元素指定。 <sphinx:schema>元素是可选的,但如果出现,就必须是
<sphinx:docset>元素的第一个子元素。如果没有在数据流中内嵌的数据模式定义,配置文件中的相关设置就会生效,否则数据流内嵌的设置被优先采用。
未知类型的标签(既不是数据字段,也不是属性的标签)会被忽略,但会给出警告。在上面的例子中,<misc>标签会被忽略。所有嵌入在其他标签中的标签及其属性都会被无视(例如上述例子中嵌入在<subject>标签中的<b>标签)
支持输入数据流的何种字符编码取决于系统中是否安装了iconv。xmlpipe2是用libexpat解析器解析的,该解析器内置对US-ASCII,ISO-8859-1,UTF-8和一些UTF-16变体的支持。
Sphinx的configure脚本也会检查libiconv是否存在并使用它来处理其他的字符编码。
libexpat也隐含的要求在Sphinx端使用UTF-8,因为它返回的分析过的数据总是UTF-8的。
xmlpipe2可以识别的XML元素(标签)(以及前述元素可用的属性)如下:
sphinx:docset
顶级元素,用于标明并包括xmlpipe2文档。
Sphinx:schema
可选元素,它要么是sphinx:docset的第一个子元素,要么干脆不出现。声明文档的模
式。包括数据字段和属性的声明。若此元素出现,则它会覆盖配置文件中对数据源的
设定。
Sphinx:field
可选元素,sphinx:schema的子元素。声明一个全文数据字段。唯一可识别的属性是
“name”,它指定了字段的名称,后续数据文档中具有此名称的元素的数据都被当作待
检索的全文数据对待。
sphinx:attr
可选元素,sphinx:schema的子元素。用于声明具体属性。其已知的属性有:
● “name”,设定该属性名称,后续文档中具有该名称的元素应被当作一个属性
对待。
● ”type”,设定该属性的类型。可能的类型包括
“int”,“timestamp”,“str2ordinal”,“bool”和“float”
● “bits”,设定“int”型属性的宽度,有效值为1到32
● “default”,设定该属性的默认值,若后续文档中没有指定这个属性,则使用此
默认值。
Sphinx:document
必须出现的元素,必须是sphinx:docset的子元素。包含任意多的其他元素,这些子元
素带有待索引的数据字段和属性值,而这些数据字段或属性值既可以是用sphinx:field
和sphinx:attr元素声明的,也可以在配置文件中声明。唯一的已知属性是“id”,它必
须包含一个唯一的整型的文档ID。
有这么一种常见的情况:整个数据集非常大,以至于难于经常性的重建索引,但是每次新增的记录却相当地少。一个典型的例子是:一个论坛有1000000个已经归档的帖子,但每天只有1000个新帖子。
在这种情况下可以用所谓的“主索引+增量索引”(main+delta)模式来实现“近实时”的
索引更新。
这种方法的基本思路是设置两个数据源和两个索引,对很少更新或根本不更新的数据建立主索引,而对新增文档建立增量索引。在上述例子中,那1000000个已经归档的帖子放在主索引中,而每天新增的1000个帖子则放在增量索引中。增量索引更新的频率可以非常快,而文档可以在出现几分种内就可以被检索到。
确定具体某一文档的分属那个索引的分类工作可以自动完成。一个可选的方案是,建立一个计数表,记录将文档集分成两部分的那个文档ID,而每次重新构建主索引时,这个表都会被更新。
示例4 全自动的即时更新
# in MySQL
CREATE TABLE sph_counter
(
counter_id INTEGER PRIMARY KEY NOT NULL,
max_doc_id INTEGER NOT NULL
);
# in sphinx.conf
source main
{
# ...
sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM documents
sql_query = SELECT id, title, body FROM documents \
WHERE id<=( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )
}
source delta : main
{
sql_query_pre =
sql_query = SELECT id, title, body FROM documents \
WHERE id>( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )
}
index main
{
source = main
path = /path/to/main
# ... all the other settings
}
# note how all other settings are copied from main,
# but source and path are overridden (they MUST be)
index delta : main
{
source = delta
path = /path/to/delta
}
注意我们如何覆写增量数据源中我sql_query_pre。这必须显式覆写它。否则REPLACE查询会创建增量索引时再次执行,。然而,当我们在继承的数据源是第一次指定这个指令时,它会删除所有继承来的值,因此编码设置也丢失了。所以增量数据源中的sql_query_pre不能置空,我们必须再次显式指定查询编码。Note how we're overriding sql_query_pre in the delta source. We need to explicitly have that override. Otherwise REPLACE query would be run when indexing delta source too, effectively nullifying it. However, when we issue the directive in the inherited source for the first time, it removes all inherited values, so the encoding setup is also lost. So sql_query_pre in the delta can not just be empty; and we need to issue the encoding setup query explicitly once again.
合并两个已有的索引比重新对所有数据做索引更有效率,而且有时候必须这样做(例如在“主索引+增量索引”分区模式中应合并主索引和增量索引,而不是简单地重新索引“主索引
对应的数据)。因此indexer有这个选项。合并索引一般比重新索引快,但在大型索引上仍
然不是一蹴而就。基本上,待合并的两个索引都会被读入内存一次,而合并后的内容需要写
入磁盘一次。例如,合并100GB和1GB的两个索引将导致202GB的IO操作(但很可能还
是比重新索引少)
基本的命令语法如下:
indexer --merge DSTINDEX SRCINDEX [--rotate]
SRCINDEX的内容被合并到DSTINDEX中,因此只有DSTINDEX索引会被改变。若
DSTINDEX已经被searchd用于提供服务,则--rotate参数是必须的。最初设计的使用模式是,
将小量的更新从SRCINDEX合并到DSTINDEX中。因此,当属性被合并时,一旦出现了重
复的文档ID,SRCINDEX中的属性值更优先(会覆盖DSTINDEX中的值)。不过要注意,
“旧的”关键字并不会被自动删除。例如,在DSTINDEX中有一个叫做“old”的关键字与文
档123相关联,而在SRCINDEX中则有关键字“new”与同一个文档相关,那么在合并后用
这两个关键字都能找到文档123。您可以给出一个显式条件来将文档从DSTINDEX中移除,
以便应对这种情况,相关的开关是--merge-dst-range:
indexer --merge main delta --merge-dst-range deleted 0 0
这个开关允许您在合并过程中对目标索引实施过滤。过滤器可以有多个,只有满足全部过滤条件的文档才会在最终合并后的索引中出现。在上述例子中,过滤器只允许“deleted”为0的那些条件通过,而去除所有标记为已删除(“deleted”)的记录(可以通过调用UpdateAttributes() 设置文档的属性)。
有如下可选的匹配模式:
SPH_MATCH_ALL, 匹配所有查询词(默认模式)
SPH_MATCH_ANY, 匹配查询词中的任意一个
SPH_MATCH_PHRASE, 将整个查询看作一个词组,要求按顺序完整匹配
SPH_MATCH_BOOLEAN, 将查询看作一个布尔表达式 (参见 节 4.2, “ 布尔查询语法 ”
SPH_MATCH_EXTENDED, 将查询看作一个Sphinx内部查询语言的表达式(参见节 4.3, “ 扩展的查询语法 ” ).在0.9.9中,这已经提升为SPH_MATCH_EXTENDED2,它提供了更强大的功能和更好的性能。本标识是为了原有的程序代码,当Sphinx及其组件,包括API 更新后,仍旧需要兼容。As of 0.9.9, this has been superceded by SPH_MATCH_EXTENDED2, providing additional functionality and better performance. The ident is retained for legacy application code that will continue to be compatible once Sphinx and its components, including the API, are upgraded.
SPH_MATCH_EXTENDED2, 匹配使用第二版本的扩展匹配模式的查询。matches query using the second version of the Extended matching mode.
SPH_MATCH_FULLSCAN, 匹配强制使用如下“完全扫描”模式的查询。该模式会忽略所有的查询项,像过滤、区间过滤和分组仍旧有效,但文本匹配除外。matches query, forcibly using the "full scan" mode as below. NB, any query terms will be ignored, such that filters, filter-ranges and grouping will still be applied, but no text-matching.
还有一个特殊的“完整扫描”(SPH_MATCH_FULLSCAN)模式,当满足如下条件时,该模式被自动激活:
1. 查询串是空的(即长度为零)
2. docinfo 存储方式为extern
在完全扫描模式中,全部已索引的文档都被看作是匹配的。这类匹配仍然会被过滤、排序或分组,但是并不会做任何真正的全文检索。这种模式可以用来统一全文检索和非全文检索的代码,或者减轻SQL服务器的负担(有些时候Sphinx扫描的速度要优于类似的MySQL查
询).An example of using the full scan mode might be to find posts in a forum. By selecting the forum's user ID via SetFilter() but not actually providing any search text, Sphinx will match every document (i.e. every post) where SetFilter() would match - in this case providing every post from that user. By default this will be ordered by relevancy, followed by Sphinx document ID in ascending order (earliest first).使用完全扫描的一个例子是找到一个论坛里的帖子数。通过SetFilter()函数但不提供任何搜索文本查询论坛的用户ID,Sphinx会匹配每个SetFilter()匹配的文档(如,每个帖子)-这种情况下提供的是这个用户的所有帖子。默认情况下将按照关联度排序,还有Sphinx文档ID的升序排列(早的在前)。
布尔查询允许使用下列特殊操作符:
显式的与(AND)操作符
hello & world
或(OR)操作符
hello | world
非(NOT)操作符
hello -world
hello !world
分组(grouping)
( hello world )
以下是一个使用了如上全部操作符的例子:
示例5 布尔查询示例
( cat -dog ) | ( cat -mouse)
与(AND)操作符为默认操作,所以“hello world”其实就是“hello & world”
或(OR)操作符的优先级高于与操作符,因此“lookingfor cat | dog | mouse”意思是"looking for (cat | dog | mouse )" 而不是 "(looking for cat) | dog | mouse"
像“-dog”这种查询不能被执行,因为它差不多包括索引所有文档。这既有技术上的原因,
也有性能上的原因。从技术上说,Sphinx并不总是保持一个全部文档ID的列表。性能方面,
当文档集非常大的时候(即10-100M个文档),对这种执行查询可能需要很长的时间。
The following special operators and modifiers can be used when using the extended matching mode: 下面的特殊操作符和修饰符可用于扩展匹配模式:
operator OR:
hello | world
operator NOT:
hello -world
hello !world
field search operator: 字段上的搜索:
@title hello @body world
field position limit modifier (introduced in version 0.9.9-rc1):
@body[50] hello
multiple-field search operator: 多字段上的搜索:
@(title,body) hello world
all-field search operator: 所有字段上的搜索:
@* hello
phrase search operator: 短语查询:???
"hello world"
proximity search operator: 相似度查询:???
"hello world"~10
quorum matching operator:
"the world is a wonderful place"/3
strict order operator (aka operator "before"): 严格顺序查询:(亦称”before”查询)
aaa << bbb << ccc
exact form modifier (introduced in version 0.9.9-rc1): 精确形式修饰符:(自0.9.9-rc1引入)???
raining =cats and =dogs
field-start and field-end modifier (introduced in version 0.9.9-rc2): 字段开始和字段结束修饰符(自0.9.9-rc2引入):
^hello world$
这有一个使用了这些操作符的查询:Here's an example query that uses some of these operators:
示例 6. 扩展查询模式:查询示例 Extended matching mode: query example
"hello world" @title "example program"~5 @body python -(php|perl) @* code
The full meaning of this search is: 完整的搜索意义是:
Find the words 'hello' and 'world' adjacently in any field in a document; 在文档的所有字段中查找相邻的'hello'和'world';
Additionally, the same document must also contain the words 'example' and 'program' in the title field, with up to, but not including, 10 words between the words in question; (E.g. "example PHP program" would be matched however "example script to introduce outside data into the correct context for your program" would not because two terms have 10 or more words between them).另外,同一文档的title字段中还必须包含'example'和'program',并且这两个词之间的单词数在10个以内;(如:”example PHP program” 是匹配的,而"example script to introduce outside data into the correct context for your program"不匹配,因为两个项之间超过10个单词了)。
Additionally, the same document must contain the word 'python' in the body field, but not contain either 'php' or 'perl'; 另外,同一文档的body字段中必须包含单词'python',但不能包含'php' 或 'perl';
Additionally, the same document must contain the word 'code' in any field.另外,同一文档任意字段中还必须包含单词'code';
There always is implicit AND operator, so "hello world" means that both "hello" and "world" must be present in matching document. 实际上这还有隐式的AND操作符,那么”hello world” 的意思是”hello”和”world”两者必须都在匹配的文档中出现。
或(OR)操作符的优先级要高于与操作符,因此"looking for cat | dog | mouse" 意思是"looking for ( cat | dog | mouse )" 而不是"(looking for cat) | dog | mouse";
Field limit operator limits subsequent searching to a given field. Normally, query will fail with an error message if given field name does not exist in the searched index. However, that can be suppressed by specifying "@@relaxed" option at the very beginning of the query:
@@relaxed @nosuchfield my query
This can be helpful when searching through heterogeneous indexes with different schemas.
Field position limit, introduced in version 0.9.9-rc1, additionaly restricts the searching to first N position within given field (or fields). For example, "@body[50] hello" will not match the documents where the keyword 'hello' occurs at position 51 and below in the body.
近似距离以词为单位,随词数变化而变化,并应用于引号中的全部词。举个例子,"cat dogmouse"~5 这个查询的意思是必须有一个少于8个词的词串,它要包含全部的三个词,也就是说"CAT aaa bbb ccc DOG eee fff MOUSE" 这个文档不会匹配这个查询,因为这个词串正好是8个词。
阀值匹配符引入了一种模糊匹配。它允许至少含有某个阈值数量个匹配词的文档通过。上述例子("the world is a wonderful place"/3)会匹配含有指定的六个词中的至少三个的那些文档。
Strict order operator (aka operator "before"), introduced in version 0.9.9-rc2, will match the document only if its argument keywords occur in the document exactly in the query order. For instance, "black << cat" query (without quotes) will match the document "black and white cat" but not the "that cat was black" document. Order operator has the lowest priority. It can be applied both to just keywords and more complex expressions, ie. this is a valid query: 自0.9.9-rc2引入 的严格顺序操作符(亦称”before”操作符)仅会匹配包含参数关键词,并且严格按照查询的顺序出现的文档。例如,”black << cat”查询(不包括引号)会匹配文档"black and white cat" ,但不会匹配"that cat was black"。顺序操作符优先级最低。它既可用于单词,也可用于更复杂的表达式,如,有这么个有效的查询:
(bag of words) << "exact phrase" << red|green|blue
Exact form keyword modifier, introduced in version 0.9.9-rc1, will match the document only if the keyword occurred in exactly the specified form. The default behaviour is to match the document if the stemmed keyword matches. For instance, "runs" query will match both the document that contains "runs" and the document that contains "running", because both forms stem to just "run" - while "=runs" query will only match the first document. Exact form operator requires index_exact_words option to be enabled. This is a modifier that affects the keyword and thus can be used within operators such as phrase, proximity, and quorum operators. 自0.9.9-rc1引入的精确形式关键字修饰符仅会匹配那些出现精确指定的形式的文档。默认匹配行为是匹配词根关键字的文档。例如,”runs”查询会匹配包含”runs”的文档和包含”running”的文档,因为这两种形式只是”run”词根的不同形式,而”=runs”查询仅会匹配第一个文档。精确形式操作符需要开启 index_exact_words选项。这是一个影响 关键字的修饰符,所以可用于phrase,proximity和quorum操作符中。
Field-start and field-end keyword modifiers, introduced in version 0.9.9-rc2, will make the keyword match only if it occurred at the very start or the very end of a fulltext field, respectively. For instance, the query "^hello world$" (with quotes and thus combining phrase operator and start/end modifiers) will only match documents that contain at least one field that has exactly these two keywords. 自0.9.9-rc2引入的字段开始和字段结束关键字修饰符匹配全文检索字段的开关或者结尾的文档。例如,查询"^hello world$"(带引号,这样是phrase操作符与开始/结束修饰符的组合)仅匹配至少有一个字段精确包含这两个关键字的文档。
自从0.9.9-rc1开始支持任意嵌套的括号和否操作。然而,该查询必须在不调用隐式文档静静的情况下能计算出来:Starting with 0.9.9-rc1, arbitrarily nested brackets and negations are allowed. However, the query must be possible to compute without involving an implicit list of all documents:
// correct query 正确的查询
aaa -(bbb -(ccc ddd))
// queries that are non-computable 不可计算的查询
-aaa
aaa | -bbb
采用何种权值计算函数(目前)取决于查询的模式。
这是权值计算函数中使用到的主要部分:
1. 词组评分
2. 统计学评分
词组评分根据文档和查询的最长公共子串(LCS,longest common subsequence)的长度进行。
因此如果文档对查询词组有一个精确匹配(即文档直接包含该词组),那么它的词组评分就取得了可能的最大值,也就是查询中词的个数。
统计学评分基于经典的BM25函数,该函数仅考虑词频。如果某词在整个数据库中很少见(即文档集上的低频词)或者在某个特定文档中被经常提及(即特定文档上的高频词),那么它就得到一个较高的权重。最终的BM25权值是一个0到1之间的浮点数。
在所有模式中,数据字段的词组评分是LCS乘以用户指定的数据字段权值。数据字段权值是整数,默认为1,且字段的权值必须不小于1。
在SPH_MATCH_BOOLEAN模式中,不做任何权重估计,每一个匹配项的权重都是1。
在SPH_MATCH_ALL和SPH_MATCH_PHRASE模式中,最终的权值是词组评分的加权和。
在SPH_MATCH_ANY模式中,于前面述两模式的基本思想类似,只是每个数据字段的权重都再加上一个匹配词数目。在那之前,带权的词组相关度被额外乘以一个足够大的数,以便确保任何一个有较大词组评分的数据字段都会使整个匹配的相关度较高,即使该数据字段的权重比较低。
在SPH_MATCH_EXTENDED模式中,最终的权值是带权的词组评分和BM25权重的和,再
乘以1000并四舍五入到整数。
这个行为将会被修改,以便使MATCH_ALL和MATCH_ANY这两个模式也能使用BM25算
法。这将使词组评分相同的搜索结果片断得到改进,这在只有一个词的查询中尤其有用。
关键的思想(对于除布尔模式以外的全部模式中)是子词组的匹配越好则评分越高,精确匹
配(匹配整个词组)评分最高。作者的经验是,这种基于词组相似性的评分方法可以提供比
任何单纯的统计模型(比如其他搜索引擎中广泛使用的BM25)明显更高的搜索质量。
可使用如下模式对搜索结果排序:
SPH_SORT_RELEVANCE 模式, 按相关度降序排列(最好的匹配排在最前面)
SPH_SORT_ATTR_DESC 模式, 按属性降序排列 (属性值越大的越是排在前面)
SPH_SORT_ATTR_ASC 模式, 按属性升序排列(属性值越小的越是排在前面)
SPH_SORT_TIME_SEGMENTS 模式, 先按时间段(最近一小时/天/周/月)降序,再按相关度降序
SPH_SORT_EXTENDED 模式, 按一种类似SQL的方式将列组合起来,升序或降序排列。
SPH_SORT_EXPR 模式,按某个算术表达式排序。
SPH_SORT_RELEVANCE忽略任何附加的参数,永远按相关度评分排序。所有其余的模式都要求额外的排序子句,子句的语法跟具体的模式有关。SPH_SORT_ATTR_ASC, SPH_SORT_ATTR_DESC以及SPH_SORT_TIME_SEGMENTS这三个模式仅要求一个属性名。
SPH_SORT_RELEVANCE模式等价于在扩展模式中按"@weight DESC, @id ASC"排序,
SPH_SORT_ATTR_ASC 模式等价于"attribute ASC, @weight DESC, @id ASC",而
SPH_SORT_ATTR_DESC 等价于"attribute DESC, @weight DESC, @id ASC"。
SPH_SORT_TIME_SEGMENTS模式
在SPH_SORT_TIME_SEGMENTS模式中,属性值被分割成“时间段”,然后先按时间段排
序,再按相关度排序。
时间段是根据搜索发生时的当前时间戳计算的,因此结果随时间而变化。所说的时间段有如下这些值:
最近一小时
最近一天
最近一星期
最近一个月
最近三个月
其他值
时间段的分法固化在搜索程序中了,但如果需要,也可以比较容易地改变(需要修改源码)。
这种模式是为了方便对Blog日志和新闻提要等的搜索而增加的。使用这个模式时,处于更近时间段的记录会排在前面,但是在同一时间段中的记录又根据相关度排序-这不同于单纯按时间戳排序而不考虑相关度。
SPH_SORT_EXTENDED 模式
在 SPH_SORT_EXTENDED 模式中,您可以指定一个类似SQL的排序表达式,但涉及的属
性(包括内部属性)不能超过5个,例如:
@relevance DESC, price ASC, @id DESC
只要做了相关设置,不管是内部属性(引擎动态计算出来的那些属性)还是用户定义的属性就都可以使用。内部属性的名字必须用特殊符号@开头,用户属性按原样使用就行了。在上面的例子里,@relevance和@id是内部属性,而price是用户定义属性。
已知的内部属性:
@id (match ID)
@weight (match weight)
@rank (match weight)
@relevance (match weight)
@random (return results in random order)
@rank和@relevance只是@weight的额外别名。
SPH_SORT_EXPR 模式
表达式排序模式使您可以对匹配项按任何算术表达式排序,表达式中的项可以是属性值,内部属性(@id和@weight),算术运算符和一些内建的函数。例如:
$cl->SetSortMode ( SPH_SORT_EXPR,
"@weight + ( user_karma + ln(pageviews) )*0.1" );
支持的运算符和函数如下。它们是模仿MySQL设计的。函数接受参数,参数的数目根据具体函数的不同而不同。
Operators: +, -, *, /, <, > <=, >=, =, <>.
Boolean operators: AND, OR, NOT.
0-argument functions: NOW().
Unary (1-argument) functions: ABS(), CEIL(), FLOOR(), SIN(), COS(), LN(), LOG2(), LOG10(), EXP(), SQRT(), BIGINT().
Binary (2-argument) functions: MIN(), MAX(), POW(), IDIV().
Other functions: IF(), INTERVAL(), IN(), GEODIST().
Calculations can be performed in three different modes: (a) using single-precision, 32-bit IEEE 754 floating point values (the default), (b) using signed 32-bit integers, (c) using 64-bit signed integers. The expression parser will automatically switch to integer mode if there are no operations the result in a floating point value. Otherwise, it will use the default floating point mode. For instance, "a+b" will be computed using 32-bit integers if both arguments are 32-bit integers; or using 64-bit integers if both arguments are integers but one of them is 64-bit; or in floats otherwise. However, "a/b" or "sqrt(a)" will always be computed in floats, because these operations return non-integer result. To avoid the first, you can use IDIV(). Also, "a*b" will not be automatically promoted to 64-bit when the arguments are 32-bit. To enforce 64-bit results, you can use BIGINT(). (But note that if there are non-integer operations, BIGINT() will simply be ignored.) 。有三种计算执行方式:(a) 使用单精度,32位IEEE 754浮点数(默认)。 (b) 使用有符号32位整数。(c) 使用64位有符号整数。如果表达式操作结果不是浮点数,那么表达式解析器会自动转到整数方式。否则,它会使用默认的浮点数方式。例如,对于”a+b”,如果两个参数都是32位整数,则会使用32位整数计算;或者 ,如果两个参数都是整数,并且其中一个是64位整数,则会使用64位整数计算方式。否则就使用浮点数方式。然而,”a/b”或sqrt(a)总会使用浮点数方式,因为这些操作都返回非整数结果。要避开前者,可以使用IDIV()函数。还有,”a*b”在参数都是32位整数的情况下不会自动转换成64位方式。要强制得到64位的结果,可以使用BIGINT()函数。(注意如果是非整数操作,则BIGINT()函数会被忽略)。
比较操作符(比如=和<=)在条件为真时返回1.0,否则返回0.0。例如(a=b)+3在属性“a”与属性“b”相等时返回4,否则返回3。与MySQL不同,相等性比较符(即=和<>)中引入了一个小的阈值(默认是1e-6)。如果被比较的两个值的差异在阈值之内,则二者被认为相等。
布尔操作符( AND, OR, NOT)自0.9.9-rc2引入,行为没什么特别的。它们是左关联操作符,它们的优先级比其他操作符低。NOT比AND和OR的优先级高,但也不高于其他的操作符。AND和OR优先级相同,因此在复杂表达式中推荐使用括号以避免出现岐义。
全部的一元和二元函数的意义都很明确,他们的行为跟在数学中的定义一样。但IF()的行为需要点详细的解释。它接受3个参数,检查第一个参数是否为0.0,若非零则返回第二个参
数,为零时则返回第三个参数。注意,与比较操作符不同,IF()并不使用阈值!因此在第一
个参数中使用比较结果是安全的,但使用算术运算符则可能产生意料之外的结果。比如,下
面两个调用会产生不同的结果,虽然在逻辑上他们是等价的:
IF ( sqrt(3)*sqrt(3)-3<>0, a, b )
IF ( sqrt(3)*sqrt(3)-3, a, b )
在第一种情况下,由于有阈值,比较操作符<>返回0.0(逻辑假),于是IF()总是返回
‘b’。在第二种情况下,IF()函数亲自在没有阈值的情况下将同样的sqrt(3)*sqrt(3)-3与零值做比较。但由于浮点数运算的精度问题,该表达式的结果与0值会有微小的差异,因此该值与零值的相等比较不会通过,上述第二种情况中IF()会返回‘a’做为结果。
BIGINT() function, introduced in version 0.9.9-rc1, forcibly promotes the integer argument to 64-bit type, and does nothing on floating point argument. It's intended to help enforce evaluation of certain expressions (such as "a*b") in 64-bit mode even though all the arguments are 32-bit. BIGINT()函数自0.9.9-rc2引入,其功能是强制整数参数转换为64位类型,但对浮点数参数没有影响。它的目的是帮助特定的表达式以64位方式求值,即使其参数为32位整数。
DIV()函数执行它2个参数的整数除法。结果也是整数,与”a/b”的结果不同。
IN(expr,val1,val2,...), introduced in version 0.9.9-rc1, takes 2 or more arguments, and returns 1 if 1st argument (expr) is equal to any of the other arguments (val1..valN), or 0 otherwise. Currently, all the checked values (but not the expression itself!) are required to be constant. (Its technically possible to implement arbitrary expressions too, and that might be implemented in the future.) Constants are pre-sorted and then binary search is used, so IN() even against a big arbitrary list of constants will be very quick. Starting with 0.9.9-rc2, first argument can also be a MVA attribute. In that case, IN() will return 1 if any of the MVA values is equal to any of the other arguments. IN(expr,val1,val2,...)函数自0.9.9-rc1引入,带两个或以上个数的参数,如果第一个参数与其他任何一个参数相等,则返回1,否则返回0.目前,所有的被测试的值(但不包括表达式自己)都必须是常量。(从技术上讲也可能实现 用表达式,或许在以后的版本中能实现)。这些常量是预先排序好的,因此可以使用二分查找算法,所以IN()函数即使有大量的参数列表,速度也非常快。自从0.9.9-rc2以来,第一个参数也可以是一个MVA属性。这种情况下,如果MVA值中的任何一个与其他任何一个参数相等,则IN()返回1.
INTERVAL(expr,point1,point2,point3,...), introduced in version 0.9.9-rc1, takes 2 or more arguments, and returns the index of the argument that is less than the first argument: it returns 0 if expr<point1, 1 if point1<=expr<point2, and so on. It is required that point1<point2<...<pointN for this function to work correctly. INTERVAL(expr,point1,point2,point3,...)函数自0.9.9-rc1引入,带两个或以上个数的参数,返回第一个小于第一个参数的位置。如果expr<point1,则返回0,,如果point1<=expr<point2则返回1,依次类推。它需要条件point1<point2<...<pointN才能正常执行。
NOW()函数自0.9.9-rc1引入,它是一个返回当前时间戳的32位整数的工具函数。
GEODIST(lat1,long1,lat2,long2) function, introduced in version 0.9.9-rc2, computes geosphere distance between two given points specified by their coordinates. Note that both latitudes and longitudes must be in radians and the result will be in meters. You can use arbitrary expression as any of the four coordinates. An optimized path will be selected when one pair of the arguments refers directly to a pair attributes and the other one is constant.GEODIST(lat1,long1,lat2,long2)函数,自0.9.9-rc2引入,计算给定的两个坐标点之间的距离。注意纬度和经度都必须在圆弧上,返回结果单位是米。四个坐标点都可以使用任意表达式。当一对直接指向一对属性而另一对是常量的时候会自动选择一个优化的路径。
有时将搜索结果分组(或者说“聚类”)并对每组中的结果计数是很有用的-例如画个漂亮的图来展示每个月有多少的blog日志,或者把Web搜索结果按站点分组,或者把找到的论坛帖子按其作者分组。
理论上,这可以分两步实现:首先在Sphinx中做全文检索,再在SQL服务器端对得到的ID分组。但是现实中在大结果集(10K到10M个匹配)上这样做通常会严重影响性能。
为避免上述问题,Sphinx提供了一种“分组模式”,可以用API调用SetGroupBy()来开启。
在分组时,根据group-by值给匹配项赋以一个分组。这个值用下列内建函数之一根据特定的
属性值计算:
SPH_GROUPBY_DAY,从时间戳中按YYYYMMDD格式抽取年、月、日
SPH_GROUPBY_WEEK,从时间戳中按YYYYNNN格式抽取年份和指定周数(自年初计起)的第一天
SPH_GROUPBY_MONTH,从时间戳中按YYYYMM格式抽取月份
SPH_GROUPBY_YEAR,从时间戳中按YYYY格式抽取年份
SPH_GROUPBY_ATTR,使用属性值自身进行分组
最终的搜索结果中每组包含一个最佳匹配。分组函数值和每组的匹配数目分别以“虚拟”属性@group和@count的形式返回。
结果集按group-by排序子句排序,语法与SPH_SORT_EXTENDED 排序子句的语法相似。除了@id和@weight,分组排序子句还包括:
@group(groupby函数值)
@count(组中的匹配数目)
默认模式是根据groupby函数值降序排列,即按照“@group desc”排序完成时,结果参数total_found会包含在整个索引上匹配的组的总数目。
注意:分组操作在固定的内存中执行,因此它给出的是近似结果;所以total_found报告的数目可能比实际给出的个分组数目的和多。@count也可能被低估。要降低不准确性,应提高max_matches。如果max_matches允许存储找到的全部分组,那结果就是百分之百准确的。
例如,如果按相关度排序,同时用SPH_GROUPBY_DAY函数按属性“published”分组,那么:
结果中包含每天的匹配结果中最相关的那一个,如果那天有记录匹配的话。
结果中还附加给出天的编号和每天的匹配数目
结果以天的编号降序排列(即最近的日子在前面)
自0.9.9-rc2开始,聚类函数(AVG(),MIN(),MAX(),SUM())可通过SetSelect() API调用用于分组查询。
为提高可伸缩性,Sphnix提供了分布式检索能力。分布式检索可以改善查询延迟问题(即缩短查询时间)和提高多服务器、多CPU或多核环境下的吞吐率(即每秒可以完成的查询数)。这对于大量数据(即十亿级的记录数和TB级的文本量)上的搜索应用来说是很关键
的。
其关键思想是将待搜索数据做水平分区(HP,Horizontally partition),然后并行处理。
分区不能自动完成,您需要:
在不同服务器上设置Sphinx程序集(indexer和searchd)的多个实例
让这些实例对数据的不同部分做索引(并检索)
在searchd的一些实例上配置一个特殊的分布式索引
然后对这个索引进行查询
这个特殊索引只包括对其他本地或远程索引的引用,因此不能对它执行重新建立索引的操作,相反,如果要对这个特殊索引进行重建,要重建的是那些被这个索引被引用到的索引。
当searchd收到一个对分布式索引的查询时,它做如下操作:
1. 连接到远程代理
2. 执行查询
3. (在远程代理执行搜索的同时)对本地索引进行查询
4. 接收来自远程代理的搜索结果
5. 将所有结果合并,删除重复项
6. 将合并后的结果返回给客户端
在应用程序看来,普通索引和分布式索引完全没有区别。也就是说,分布式索引对于应用程序来说是透明的,没有办法知道你的查询使用的是分布式索引还是本地索引。(即使在0.9.9中,Sphinx不允许通过分布式索引和其他任何索引执行搜索,这一约束在以后也将继续)。That is, distributed indexes are fully transparent to the application, and actually there's no way to tell whether the index you queried was distributed or local. (Even though as of 0.9.9 Sphinx does not allow to combine searching through distributed indexes with anything else, this constraint will be lifted in the future.)
任一个searchd实例可以同时做为主控端(master,对搜索结果做聚合)和从属端(只做本地搜索)。这有如下几点好处:
1. 集群中的每台机器都可以做为主控端来搜索整个集群,搜索请求可以在主控端之间获
得负载平衡,相当于实现了一种HA(high availability,高可用性),可以应对某个
节点失效的情况。
2. 如果在单台多CPU或多核机器上使用,一个做为代理对本机进行搜索的searchd实例
就可以利用到全部的CPU或者核。
更好的HA支持已在计划之中,到时将允许指定哪些代理之间互相备份、有效性检查、跟踪运行中的代理、对检索请求进行负载均衡,等等。
searchd将全部成功执行的搜索查询都记录在查询日志文件中。以下是一个类似记录文件的例子:
[Fri Jun 29 21:17:58 2007] 0.004 sec [all/0/rel 35254 (0,20)] [lj] test
[Fri Jun 29 21:20:34 2007] 0.024 sec [all/0/rel 19886 (0,20) @channel_id] [lj]test
日志格式如下
[query-date] query-time [match-mode/filters-count/sort-mode
total-matches (offset,limit) @groupby-attr] [index-name] query
匹配模式(match-mode)可以是如下值之一:
"all" 代表 SPH_MATCH_ALL 模式;
"any" 代表 SPH_MATCH_ANY 模式;
"phr" 代表 SPH_MATCH_PHRASE 模式;
"bool" 代表 SPH_MATCH_BOOLEAN 模式;
"ext" 代表 SPH_MATCH_EXTENDED 模式.
排序模式(sort-mode)可以取如下值之一:
"rel" 代表 SPH_SORT_RELEVANCE 模式;
"attr-" 代表 SPH_SORT_ATTR_DESC 模式;
"attr+" 代表 SPH_SORT_ATTR_ASC 模式;
"tsegs" 代表 SPH_SORT_TIME_SEGMENTS 模式;
"ext" 代表 SPH_SORT_EXTENDED 模式.
Additionally, if searchd was started with --iostats, there will be a block of data after where the index(es) searched are listed.另外,如果searchd是带参数--iostats启动的,那么在搜索的索引后有一块数据。
A query log entry might take the form of:查询日志持上去可能像下面这格式:
[Fri Jun 29 21:17:58 2007] 0.004 sec [all/0/rel 35254 (0,20)] [lj] [ios=6 kb=111.1 ms=0.5] test
This additional block is information regarding I/O operations in performing the search: the number of file I/O operations carried out, the amount of data in kilobytes read from the index files and time spent on I/O operations (although there is a background processing component, the bulk of this time is the I/O operation time)。这一附加块表示搜索执行时的I/O信息:用到了多少个文件I/O操作,从索引文件中读取了多少K的数据和用在I/O操作上的时间(虽然有一个后端处理组件,这块时间还是I.O操作时间)。
Starting with version 0.9.9-rc2, Sphinx searchd daemon supports MySQL binary network protocol and can be accessed with regular MySQL API. For instance, 'mysql' CLI client program works well. Here's an example of querying Sphinx using MySQL client: 自0.9.9-rc2开始,Sphinx的searchd守护进程支持MySQL二进制网络协议,并且可以使用通用的MySQL API访问它。例如,'mysql'命令行客户端程序运行良好。这有一个使用MySQL客户端查询Sphinx的示例:
$ mysql -P 3307
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 0.9.9-dev (r1734)
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> SELECT * FROM test1 WHERE MATCH('test')
-> ORDER BY group_id ASC OPTION ranker=bm25;
+------+--------+----------+------------+
| id | weight | group_id | date_added |
+------+--------+----------+------------+
| 4 | 1442 | 2 | 1231721236 |
| 2 | 2421 | 123 | 1231721236 |
| 1 | 2421 | 456 | 1231721236 |
+------+--------+----------+------------+
3 rows in set (0.00 sec)
Note that mysqld was not even running on the test machine. Everything was handled by searchd itself. 注意测试机器上没有运行mysqld。所有的工作都是searchd自己处理的。
The new access method is supported in addition to native APIs which all still work perfectly well. In fact, both access methods can be used at the same time. Also, native API is still the default access method. MySQL protocol support needs to be additionally configured. This is a matter of 1-line config change, adding a new listener with mysql41 specified as a protocol: 这种新的运访问方式作为本地API的额外支持的,但它们都运行好非常好。事实上,两种访问方式可以同时使用。另外,本地API是默认的访问方式。MySQL协议支持需要另外的配置。这只涉及到1行配置更改,中需要添加一个新的使用指定的mysql41协议的listener。
listen = localhost:9306:mysql41
Just supporting the protocol and not the SQL syntax would be useless so Sphinx now also supports a tiny subset of SQL that we dubbed SphinxQL. Currently implemented statements are: 虽然支持了协议,但不是完整的SQL语法都支持,Sphinx现在只支持SQL的一个小的子集,叫做SphinxQL。现在已经实现的语句有:
SELECT
SHOW WARNINGS
SHOW STATUS
SHOW META
SELECT syntax is based upon regular SQL but adds several Sphinx-specific extensions and has a few omissions (such as (currently) missing support for JOINs). Specifically,
Column list clause. Column names, arbitrary expressions, and star ('*') are all allowed (ie. "SELECT @id, group_id*123+456 FROM test1" will work). Unlike in regular SQL, all computed expressions must be aliased with a valid identifier. Special names such as @id and @weight should currently be used with leading at-sign. This at-sign requirement will be lifted in the future. SELECT语法基于通用的SQL,加入了几个Sphinx相关的扩展,还删掉了一些(如现在不支持JOIN了)。特别要指出的是,列列表语句,列名,任意表达式和星('*')都是允许的(例如,"SELECT @id, group_id*123+456 FROM test1"能够执行)。与通用SQL不现,所有的计算表达式必须给一个有效的标识符作为别名。特殊的名字,像@id和@weight现在应该在前面带上@符号。这个@符号的限制在以后可能去掉。
FROM clause. FROM clause should contain the list of indexes to search through. Unlike in regular SQL, comma means enumeration of full-text indexes as in Query() API call rather than JOIN. FROM语句。FROM语句应该包含要搜索的索引列表。与通用SQL不同的是,逗号的意思是枚举全文索引,正如Query() API调用一样,而不是JOIN。
WHERE clause. This clause will map both to fulltext query and filters. Comparison operators (=, !=, <, >, <=, >=), IN(), AND, NOT, and BETWEEN are all supported and map directly to filters. OR is not supported yet but will be in the future. MATCH('query') is supported and maps to fulltext query. Query will be interpreted according to full-text query language rules. There must be at most one MATCH() in the clause. WHERE语句。WHERE语句包含了全文检索和过滤。比较操作符(=,!=,<,>,<=,>=),IN(), AND , NOT 和 BETWEEN都被支持,直接映射到过滤器上。OR 目前还不支持,不过以后可能支持。MATCH('query')被支持,并直接映射到全文检索上。查询部分会被解释为全文检索语言规则。一个语言中最多只有有一个MATCH()。
GROUP BY clause. Currently only supports grouping by a single column. The column however can be a computed expression: GROUP BY语句。目前仅支持单一列分组。该列可以是计算表达式:
SELECT *, group_id*1000+article_type AS gkey FROM example GROUP BY gkey
Aggregate functions (AVG(), MIN(), MAX(), SUM()) in column list clause are supported. Arguments to aggregate functions can be either plain attributes or arbitrary expressions. COUNT(*) is implicitly supported as using GROUP BY will add @count column to result set. Explicit support might be added in the future. COUNT(DISTINCT attr) is supported. Currently there can be at most one COUNT(DISTINCT) per query and an argument needs to be an attribute. Both current restrictions on COUNT(DISTINCT) might be lifted in the future. 在语句中的聚合函数(AVG(), MIN(), MAX(),SUM())是被支持的。聚合函数的参数可以是文本的属性或者任意的表达式。COUNT(*)是隐式支持的,因为在使用GROUP By的时候会在结果集加@count列。显式支持可能在以后支持。COUNT(DISTINCT attr)也是支持的。目前一个查询中最多只能有一个COUNT(DISTINCT),并且参数必须是一个属性。COUNT(DISTINCT)的这两个限制可能在以后版本中去掉。
SELECT *, AVG(price) AS avgprice, COUNT(DISTINCT storeid)
FROM products
WHERE MATCH('ipod')
GROUP BY vendorid
WITHIN GROUP ORDER BY clause. This is a Sphinx specific extension that lets you control how the best row within a group will to be selected. The syntax matches that of regular ORDER BY clause: WITHIN GROUP ORDER BY 语句。这是一个Sphinx特有的扩展,让你控制选择分组内的最好的行:
SELECT *, INTERVAL(posted,NOW()-7*86400,NOW()-86400) AS timeseg
FROM example WHERE MATCH('my search query')
GROUP BY siteid
WITHIN GROUP ORDER BY @weight DESC
ORDER BY timeseg DESC, @weight DESC
ORDER BY clause. Unlike in regular SQL, only column names (not expressions) are allowed and explicit ASC and DESC are required. The columns however can be computed expressions: ORDER BY语句。与通用的SQL不同,它仅支持列名(非表达式),并且需要显式的指定ASC和DESC。然而列可以是计算表达式工:
SELECT *, @weight*10+docboost AS skey FROM example ORDER BY skey
LIMIT clause. Both LIMIT N and LIMIT M,N forms are supported. Unlike in regular SQL (but like in Sphinx API), an implicit LIMIT 0,20 is present by default. LIMIT语句。同时支持LIMIT N和LIMIT M,N。与通用SQL不同(但与Sphinx API中相信),默认情况下使用隐式的LIMIT 0,20。
OPTION clause. This is a Sphinx specific extension that lets you control a number of per-query options. The syntax is: OPTION语句。这是Sphinx特有的扩展,让你控制每次查询的选项。语法如下:
OPTION <optionname>=<value> [ , ... ]
支持的选项及相应的值有:
'ranker' - any of 'proximity_bm25', 'bm25', 'none', 'wordcount', 'proximity', 'matchany', or 'fieldmask'
'max_matches' - integer (per-query max matches value)
'cutoff' - integer (max found matches threshold)
'max_query_time' - integer (max search time threshold, msec)
'retry_count' - integer (distributed retries count)
'retry_delay' - integer (distributed retry delay, msec)
示例:
SELECT * FROM test WHERE MATCH('@title hello @body world')
OPTION ranker=bm25, max_matches=3000
SHOW WARNINGS statement can be used to retrieve the warning produced by the latest query. The error message will be returned along with the query itself: SHOW WARNINGS 语句用于获取最近一次查询产生的警告信息。错误信息会和查询结果一起返回:
mysql> SELECT * FROM test1 WHERE MATCH('@@title hello') \G
ERROR 1064 (42000): index test1: syntax error, unexpected TOK_FIELDLIMIT
near '@title hello'
mysql> SELECT * FROM test1 WHERE MATCH('@title -hello') \G
ERROR 1064 (42000): index test1: query is non-computable (single NOT operator)
mysql> SELECT * FROM test1 WHERE MATCH('"test doc"/3') \G
*************************** 1. row ***************************
id: 4
weight: 2500
group_id: 2
date_added: 1231721236
1 row in set, 1 warning (0.00 sec)
mysql> SHOW WARNINGS \G
*************************** 1. row ***************************
Level: warning
Code: 1000
Message: quorum threshold too high (words=2, thresh=3); replacing quorum operator
with AND operator
1 row in set (0.00 sec)
SHOW STATUS shows a number of useful performance counters. IO and CPU counters will only be available if searchd was started with --iostats and --cpustats switches respectively. SHOW STATUS显式一系列有用的性能计数器。仅当searchd 以--iostats和--cpustats开关启动时IO和CPU计数器才可用。
mysql> SHOW STATUS;
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| uptime | 216 |
| connections | 3 |
| maxed_out | 0 |
| command_search | 0 |
| command_excerpt | 0 |
| command_update | 0 |
| command_keywords | 0 |
| command_persist | 0 |
| command_status | 0 |
| agent_connect | 0 |
| agent_retry | 0 |
| queries | 10 |
| dist_queries | 0 |
| query_wall | 0.075 |
| query_cpu | OFF |
| dist_wall | 0.000 |
| dist_local | 0.000 |
| dist_wait | 0.000 |
| query_reads | OFF |
| query_readkb | OFF |
| query_readtime | OFF |
| avg_query_wall | 0.007 |
| avg_query_cpu | OFF |
| avg_dist_wall | 0.000 |
| avg_dist_local | 0.000 |
| avg_dist_wait | 0.000 |
| avg_query_reads | OFF |
| avg_query_readkb | OFF |
| avg_query_readtime | OFF |
+--------------------+-------+
29 rows in set (0.00 sec)
SHOW META shows additional meta-information about the latest query such as query time and keyword statistics: SHOW META显示最近一次查询的附加信息,如用时和关键字统计:
mysql> SELECT * FROM test1 WHERE MATCH('test|one|two');
+------+--------+----------+------------+
| id | weight | group_id | date_added |
+------+--------+----------+------------+
| 1 | 3563 | 456 | 1231721236 |
| 2 | 2563 | 123 | 1231721236 |
| 4 | 1480 | 2 | 1231721236 |
+------+--------+----------+------------+
3 rows in set (0.01 sec)
mysql> SHOW META;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| total | 3 |
| total_found | 3 |
| time | 0.005 |
| keyword[0] | test |
| docs[0] | 3 |
| hits[0] | 5 |
| keyword[1] | one |
| docs[1] | 1 |
| hits[1] | 2 |
| keyword[2] | two |
| docs[2] | 1 |
| hits[2] | 2 |
+---------------+-------+
12 rows in set (0.00 sec)
new for sphinx 0.9.9
search is one of the helper tools within the Sphinx package. Whereas searchd is responsible for searches in a server-type environment, search is aimed at testing the index from the command line, and testing the index quickly without building a framework to make the connection to the server and process its response.
search是Sphinx包中的一个帮助工具。Searchd的功能是 提供服务器端环境的搜索功能,search目标是以命令行的方式测试索引,可以快速的测试索引而不用创建一个的需要连结到服务器并处理返回结果的完整构架。
Note: search is not intended to be deployed as part of a client application; it is strongly recommended you do not write an interface to search instead of searchd, and none of the bundled client APIs support this method. (In any event, search will reload files each time, whereas searchd will cache them in memory for performance.)
注意:search程序并不是为了作为一个客户端应用的一部分;推荐你不要写一个面向search却不用searchd的接口,没有支持这种方法的相应的客户端API绑定。(不论什么条件,search总会在每次搜索的时候重新加载一次索引,但searchd会为了性能把索引缓存在内存中)
That said, many types of query that you could build in the APIs could also be made with search, however for very complex searches it may be easier to construct them using a small script and the corresponding API. Additionally, some newer features may be available in the searchd system that have not yet been brought into search.
或许有人说,可以使用API创建的查询也同样可用search程序实现,但对于 非常复杂的查询,可能使用相应的API创建一个小脚本更容易。另外,有些新功能已经在searchd系统中实现,但还没有移植到search程序中。
search程序调用语法:
search [OPTIONS] word1 [word2 [word3 [...]]]
When calling search, it is not necessary to have searchd running; simply that the account running search has read access to the configuration file and the location and files of the indexes.
在调用search的时候,searchd不必在正在运行;只需要search能访问配置文件和相应位置的索引文件。
The default behaviour is to apply a search for word1 (AND word2 AND word3... as specified) to all fields in all indexes as given in the configuration file. If constructing the equivalent in the API, this would be the equivalent to passing SPH_MATCH_ALL to SetMatchMode, and specifying * as the indexes to query as part of Query.
Search程序的默认行为是在配置文件中包含的所有索引中的所有字段上查询word1 (AND word2 AND word3...)。如果要构建等价的API的话,相当于给SetMatchMode传递SPH_MATCH_ALL,指定*作为Query的索引。
There are many options available to search. Firstly, the general options: search程序有许多可用选项,其中最基本的是:
--config <file> (-c <file> for short) tells search to use the given file as its configuration, just as with indexer above.
--index <index> (-i <index> for short) tells search to limit searching to the specified index only; normally it would attempt to search all of the physical indexes listed in sphinx.conf, not any distributed ones.
--stdin tells search to accept the query from the standard input, rather than the command line. This can be useful for testing purposes whereby you could feed input via pipes and from scripts.
Options for setting matches: 设置匹配的选项:
--any (-a for short) changes the matching mode to match any of the words as part of the query (word1 OR word2 OR word3). In the API this would be equivalent to passing SPH_MATCH_ANY to SetMatchMode.改变匹配模式为匹配查询中的任意一个词(word1 OR word2 OR word3)。在API中,它等价于给SetMatchMode传递SPH_MATCH_ANY。
--phrase (-p for short) changes the matching mode to match all of the words as part of the query, and do so in the phrase given (not including punctuation). In the API this would be equivalent to passing SPH_MATCH_PHRASE to SetMatchMode.改变匹配模式为匹配查询中的所有词,and do so in the phrase given (not including punctuation). 在API中,它等价于给SetMatchMode传递SPH_MATCH_PHRASE。
--boolean (-b for short) changes the matching mode to Boolean matching. Note if using Boolean syntax matching on the command line, you may need to escape the symbols (with a backslash) to avoid the shell/command line processor applying them, such as ampersands being escaped on a Unix/Linux system to avoid it forking to the search process, although this can be resolved by using --stdin, as below. In the API this would be equivalent to passing SPH_MATCH_BOOLEAN to SetMatchMode.改变匹配模式为布尔匹配模式。注意如果在命令行使用布布尔匹配语法,你需要逃逃逸特殊符号(使用反斜线)以避免shell/命令行处理器变动它们,&符号应该在Unix/Linux系统逃逸以避免search进程后台运行,当然如上所说也可用--stdin选项避免这个问题。在API中,它等价于给SetMatchMode传递SPH_MATCH_BOOLEAN。
--ext (-e for short) changes the matching mode to Extended matching. In the API this would be equivalent to passing SPH_MATCH_EXTENDED to SetMatchMode, and it should be noted that use of this mode is being discouraged in favour of Extended2, below.改变匹配模式为扩展模式。在API中,它等价于给SetMatchMode传递SPH_MATCH_EXTENDED,注意更推荐使用下面的Extended2而不提倡用这个。
--ext2 (-e2 for short) changes the matching mode to Extended matching, version 2. In the API this would be equivalent to passing SPH_MATCH_EXTENDED2 to SetMatchMode, and it should be noted that use of this mode is being recommended in favour of Extended, due to being more efficient and providing other features.改变匹配模式为扩展模式v2。在API中,它等价于给SetMatchMode传递SPH_MATCH_EXTENDED2,这个模式是非常推荐的,它带来了其他的功能和效率改进。
--filter <attr> <v> (-f <attr> <v> for short) filters the results such that only documents where the attribute given (attr) matches the value given (v). For example, --filter deleted 0 only matches documents with an attribute called 'deleted' where its value is 0. You can also add multiple filters on the command line, by specifying multiple --filter multiple times, however if you apply a second filter to an attribute it will override the first defined filter.过滤结果,只保留给定的属性attr匹配给定的值v的文档。例如,--filter deleted 0仅包含属性叫deleted并且值为0的文档。然而如果再指定第二个过滤属性,则它会覆盖第一个定义的过滤。
处理结果的选项:
--limit <count> (-l count for short) limits the total number of matches back to the number given. If a 'group' is specified, this will be the number of grouped results. This defaults to 20 results if not specified (as do the APIs)
--offset <count> (-o <count> for short) offsets the result list by the number of places set by the count; this would be used for pagination through results, where if you have 20 results per 'page', the second page would begin at offset 20, the third page at offset 40, etc.
--group <attr> (-g <attr> for short) specifies that results should be grouped together based on the attribute specified. Like the GROUP BY clause in SQL, it will combine all results where the attribute given matches, and returns a set of results where each returned result is the best from each group. Unless otherwise specified, this will be the best match on relevance.
--groupsort <expr> (-gs <expr> for short) instructs that when results are grouped with -group, the expression given in <expr> shall determine the order of the groups. Note, this does not specify which is the best item within the group, only the order in which the groups themselves shall be returned.
--sortby <clause> (-s <clause> for short) specifies that results should be sorted in the order listed in <clause>. This allows you to specify the order you wish results to be presented in, ordering by different columns. For example, you could say --sortby "@weight DESC entrytime DESC" to sort entries first by weight (or relevance) and where two or more entries have the same weight, to then sort by the time with the highest time (newest) first. You will usually need to put the items in quotes (--sortby "@weight DESC") or use commas (--sortby @weight,DESC) to avoid the items being treated separately. Additionally, like the regular sorting modes, if --group (grouping) is being used, this will state how to establish the best match within each group.
--sortexpr expr (-S expr for short) specifies that the search results should be presented in an order determined by an arithmetic expression, stated in expr. For example: --sortexpr "@weight + ( user_karma + ln(pageviews) )*0.1" (again noting that this will have to be quoted to avoid the shell dealing with the asterisk). Extended sort mode is discussed in more detail under the SPH_SORT_EXTENDED entry under the Sorting modes chapter of the manual.
--sort=date specifies that the results should be sorted by descending (i.e. most recent first) date. This requires that there is an attribute in the index that is set as a timestamp.
--rsort=date specifies that the results should be sorted by ascending (i.e. oldest first) date. This requires that there is an attribute in the index that is set as a timestamp.
--sort=ts specifies that the results should be sorted by timestamp in groups; it will return all of the documents whose timestamp is within the last hour, then sorted within that bracket for relevance. After, it would return the documents from the last day, sorted by relevance, then the last week and then the last month. It is discussed in more detail under the SPH_SORT_TIME_SEGMENTS entry under the Sorting modes chapter of the manual.
Other options:
--noinfo (-q for short) instructs search not to look-up data in your SQL database. Specifically, for debugging with MySQL and search, you can provide it with a query to look up the full article based on the returned document ID. It is explained in more detail under the sql_query_info directive.
Sphnix有几种不同编程语言的searchd客户端API的实现。在本文完成之时,我们对我们自己的PHP,Python和java实现提供官方支持。此外,也有一些针对Perl,Ruby和C++的第
三方免费、开源API实现。
API的参考实现是用PHP写成的,因为(我们相信)较之其他语言,Sphinx在PHP中应用
最广泛。因此这份参考文档基于PHP API的参考,而且这节中的所有的代码样例都用PHP
给出。
当然,其他所有API都提供相同的方法,也使用完全相同的网络协议。因此这份文档对他们同样适用。在方法命名习惯方面或者具体数据结构的使用上可能会有小的差别。但不同语言的API提供的功能上绝不会有差异。
原型: function GetLastError()
以人类可读形式返回最近的错误描述信息。如果前一次API调用没有错误,返回空字符串。
任何其他函数(如 Query())失败后(函数失败一般返回false),都应该调用这个函数,它
将返回错误的描述。
此函数本身并不重置对错误描述,因此如有必要,可以多次调用。
以人类可读格式返回最近的警告描述信息。如果前一次API调用没有警告,返回空字符串。
您应该调用这个函数来确认您的请求(如 Query())是否虽然完成了但产生了警告。例如,
即使几个远程代理超时了,对分布式索引的搜索查询也可能成功完成。这时会产生一个警告
信息。
此函数本身不会重置警告信息,因此如有必要,可以多次调用。
原型:function SetServer ( $host, $port )
设置searchd的主机名和TCP端口。此后的所有请求都使用新的主机和端口设置。默认的主
机和端口分别是“localhost”和3312。
原型: function SetRetries ( $count, $delay=0 )
设置分布式搜索重试的次数和延迟时间。
对于暂时的失败,searchd对每个代理重试至多$count次。$delay是两次重试之间延迟的时间,
以毫秒为单位。默认情况下,重试是禁止的。注意,这个调用不会使API本身对暂时失败进
行重试,它只是让searchd这样做。目前暂时失败包括connect()调用的各种失败和远程代理
超过最大连接数(过于繁忙)的情况。
原型: function SetConnectTimeout ( $timeout )
Sets the time allowed to spend connecting to the server before giving up. 设置放弃之前连接服务器超时时间。
Under some circumstances, the server can be delayed in responding, either due to network delays, or a query backlog. In either instance, this allows the client application programmer some degree of control over how their program interacts with searchd when not available, and can ensure that the client application does not fail due to exceeding the script execution limits (especially in PHP). 在某些情况下,服务器可能由于网络延迟,或者等待一个查询等时可能会延迟响应,这个方法允许客户端程序员在searchd不可用时有一定的控制,以保证客户端程序不会转为脚本超时(尤其在PHP中)而失败。
In the event of a failure to connect, an appropriate error code should be returned back to the application in order for application-level error handling to advise the user.连接失败的时候会返回一个合适的错误代码,应用程序可以处理这个错误并通知用户。
原型: function SetArrayResult ( $arrayresult )
PHP专用。控制搜索结果集的返回格式(匹配项按数组返回还是按hash返回)
$arrayresult参数应为布尔型。如果$arrayresult为假(默认),匹配项以PHP hash格式返回,
文档ID为键,其他信息(权重、属性)为值。如果$arrayresult为真,匹配项以普通数组返
回,包括匹配项的全部信息(含文档ID)
这个调用是对MVA属性引入分组支持时同时引入的。对MVA分组的结果可能包含重复的
文档ID。因此需要将他们按普通数组返回,因为hash对每个文档ID仅能保存一个记录。
原型: function IsConnectError ()
Checks whether the last error was a network error on API side, or a remote error reported by searchd. Returns true if the last connection attempt to searchd failed on API side, false otherwise (if the error was remote, or there were no connection attempts at all). Introduced in version 0.9.9-rc1.检查最后一个错误是否是API端的网络错误,还是远程searchd报告的错误。返回true表示连接searchd失败在API端,false表示其他错误(可能错误是远程的,也可能没有任何连接企图)。自0.9.9-rc1引入。
原型: function SetLimits ( $offset, $limit, $max_matches=0, $cutoff=0 )
给服务器端结果集设置一个偏移量($offset)和从那个偏移量起向客户端返回的匹配项数目
限制($limit)。并且可以在服务器端设定当前查询的结果集大小($max_matches),另有
一个阈值($cutoff),当找到的匹配项达到这个阀值时就停止搜索。全部这些参数都必须是
非负整数。
前两个参数的行为与MySQL LIMIT子句中参数的行为相同。他们令searchd从编号为$offset
的匹配项开始返回最多$limit个匹配项。偏移量($offset)和结果数限制($limit)的默认值分别是0和20,即返回前20个匹配项。
max_match这个设置控制搜索过程中searchd在内存中所保持的匹配项数目。一般来说,即
使设置了max_matches为1,全部的匹配文档也都会被处理、评分、过滤和排序。但是任一
时刻只有最优的N个文档会被存储在内存中,这是为了性能和内存使用方面的原因,这个设
置正是控制这个N的大小。注意,max_matches在两个地方设置。针对单个查询的限制由这
个API调用指定。但还有一个针对整个服务器的限制,那是由配置文件中的max_matches设
置控制的。为防止滥用内存,服务器不允许单个查询的限制高于服务器的限制。
在客户端不可能收到超过max_matches个匹配项。默认的限制是1000,您应该不会遇到需要设置得更高的情况。1000个记录足够向最终用户展示了。如果您是想将结果传输给应用程序以便做进一步排序或过滤,那么请注意,在Sphinx端完成效率要高得多。
$cutoff设置是为高级性能优化而提供的。它告诉searchd 在找到并处理$cutoff个匹配后就强
制停止。
原型: function SetMaxQueryTime ( $max_query_time )
设置最大搜索时间,以毫秒为单位。参数必须是非负整数。默认值为0,意思是不做限制。
这个设置与SetLimits()中的$cutoff相似,不过这个设置限制的是查询时间,而不是处理的匹
配数目。一旦处理时间已经太久,本地搜索查询会被停止。注意,如果一个搜索查询了多个
本地索引,那这个限制独立地作用于这几个索引。
原型: function SetOverride ( $attrname, $attrtype, $values )
Sets temporary (per-query) per-document attribute value overrides. Only supports scalar attributes. $values must be a hash that maps document IDs to overridden attribute values. Introduced in version 0.9.9-rc1. 设置临时的(本次查询)文档属性值覆写。仅支持shi量属性。$values必须是一个key值为文档ID,value值为属性值的哈希表。自0.9.9-rc1引入。
Override feature lets you "temporary" update attribute values for some documents within a single query, leaving all other queries unaffected. This might be useful for personalized data. For example, assume you're implementing a personalized search function that wants to boost the posts that the user's friends recommend. Such data is not just dynamic, but also personal; so you can't simply put it in the index because you don't want everyone's searches affected. Overrides, on the other hand, are local to a single query and invisible to everyone else. So you can, say, setup a "friends_weight" value for every document, defaulting to 0, then temporary override it with 1 for documents 123, 456 and 789 (recommended by exactly the friends of current user), and use that value when ranking.覆写特性允许你“临时地”在本次查询中更新某些文档的属性,但不影响其他的查询。这可能对一些私人化数据有用。例如,假设你实现了一个想查找用户好友推荐的发帖的私人化搜索功能。这些数据不仅是动态的,还是私人的;那么你不能简单地把它放在索引中,因为你不希望每个人的搜索都受影响。或者说覆写是针对本次查询的,其他人看不到的。那么你可以为所有文档创建一个friends_witght值,默认为0,然后临时地对文档123,456,789覆写为1(推荐当前好友的朋友列表),在打分的时候使用这些值。
原型: function SetSelect ( $clause )
Sets the select clause, listing specific attributes to fetch, and expressions to compute and fetch. Clause syntax mimics SQL. Introduced in version 0.9.9-rc1.设置查询语句,列出要获取的特定的属性,要计算并获取的表达式。语句语法与SQL类似。自0.9.9-rc1引入。
SetSelect() is very similar to the part of a typical SQL query between SELECT and FROM. It lets you choose what attributes (columns) to fetch, and also what expressions over the columns to compute and fetch. A certain difference from SQL is that expressions must always be aliased to a correct identifier (consisting of letters and digits) using 'AS' keyword. SQL also lets you do that but does not require to. Sphinx enforces aliases so that the computation results can always be returned under a "normal" name in the result set, used in other clauses, etc. SetSelect()与典型的SQL语句中SELECT和FROM之间的部分相似。它让你选择获取什么属性(列),以及要计算并获取的列表达式。与SQL的不同在于,表达式必须用”AS”起个有效的标识符别名(由字母和数据组成)。SQL也允许这么做但并不强求。Sphinx强制用别名以便计算结果能通过“正常的”名字出现的结果集中,则可用于其他语句等。
Everything else is basically identical to SQL. Star ('*') is supported. Functions are supported. Arbitrary amount of expressions is supported. Computed expressions can be used for sorting, filtering, and grouping, just as the regular attributes.
Starting with version 0.9.9-rc2, aggregate functions (AVG(), MIN(), MAX(), SUM()) are supported when using GROUP BY. 其他的都是QL一致。星号(*)支持。函数支持。任意个数表达式支持。计算出的表达式可以像正规的属性一样用于排序、过滤、分组。
Expression sorting (Section 4.5, “SPH_SORT_EXPR mode”) and geodistance functions (Section 6.4.5, “SetGeoAnchor”) are now internally implemented using this computed expressions mechanism, using magic names '@expr' and '@geodist' respectively.
Example:表达式排序(见4.5,“SPH_SORT_EXPR模式”)和距离函数(见 6.4.5,”SetGeoAnchor”)内部实现都是通过表达式计算实现的。例如:
$cl->SetSelect ( "*, @weight+(user_karma+ln(pageviews))*0.1 AS myweight" );
$cl->SetSelect ( "exp_years, salary_gbp*{$gbp_usd_rate} AS salary_usd,
IF(age>40,1,0) AS over40" );
$cl->SetSelect ( "*, AVG(price) AS avgprice" );
原型: function SetMatchMode ( $mode )
设置全文查询的匹配模式,参见节4.1 “匹配模式”中的描述。参数必须是一个与某个已知模
式对应的常数。
警告:(仅PHP)查询模式常量不能包含在引号中,那给出的是一个字符串而不是一个常量。
$cl->SetMatchMode ( "SPH_MATCH_ANY" ); // INCORRECT! will not work as expected
$cl->SetMatchMode ( SPH_MATCH_ANY ); // correct, works OK
原型: function SetRankingMode ( $ranker )
设置评分模式。目前只在SPH_MATCH_EXTENDED2这个匹配模式中提供。参数必须是与
某个已知模式对应的常数。
Sphinx默认计算两个对最终匹配权重有用的因子。主要是查询词组与文档文本的相似度。其
次是称之为BM25的统计函数,该函数值根据关键字文档中的频率(高频导致高权重)和在
整个索引中的频率(低频导致高权重)在0和1之间取值。
然而,有时可能需要换一种计算权重的方法——或者可能为了提高性能而根本不计算权值,
结果集用其他办法排序。这个目的可以通过设置合适的相关度计算模式来达到。
已经实现的模式包括:
SPH_RANK_PROXIMITY_BM25, 默认模式,同时使用词组评分和BM25评分,并且将二者结合。
SPH_RANK_BM25,统计相关度计算模式,仅使用BM25评分计算(与大多数全文检索引擎相同)。这个模式比较快,但是可能使包含多个词的查询的结果质量下降。
SPH_RANK_NONE,禁用评分的模式,这是最快的模式。实际上这种模式与布尔搜索相同。所有的匹配项都被赋予权重1。
SPH_RANK_WORDCOUNT, 通过关键字出现次数评分。这个评分规则计算每个字段的关键字出现次数,然后数量乘以字段权重,然后两者累加得到最后的计算结果。ranking by keyword occurrences count. This ranker computes the amount of per-field keyword occurrences, then multiplies the amounts by field weights, then sums the resulting values for the final result.
SPH_RANK_PROXIMITY, 自0.9.9-rc1引入,返回原始的词组相似度值作为结果。这种模式在内部用于模拟SPH_MATCH_ALL查询。added in version 0.9.9-rc1, returns raw phrase proximity value as a result. This mode is internally used to emulate SPH_MATCH_ALL queries.
SPH_RANK_MATCHANY, 自0.9.9-rc1引入,返回评分,就像前面SPH_MATCH_ANY中计算出来的一样。added in version 0.9.9-rc1, returns rank as it was computed in SPH_MATCH_ANY mode ealier, and is internally used to emulate SPH_MATCH_ANY queries.
SPH_RANK_FIELDMASK, 自0.9.9-rc2引入,返回32位掩码,第N位对应全文检索中的第N个字段,数字N从0开始。仅当相应的字段与关键字匹配时该位才会设置。added in version 0.9.9-rc2, returns a 32-bit mask with N-th bit corresponding to N-th fulltext field, numbering from 0. The bit will only be set when the respective field has any keyword occurences satisfiying the query.
原型: function SetSortMode ( $mode, $sortby="" )
设置匹配项的排序模式,见 节 4.5, “ 排序模式” 中的描述。参数必须为与某个已知模式对应
的常数。
警告:(仅PHP)查询模式常量不能包含在引号中,那给出的是一个字符串而不是一个常量。
$cl->SetSortMode ( "SPH_SORT_ATTR_DESC" ); // INCORRECT! will not work as
expected
$cl->SetSortMode ( SPH_SORT_ATTR_ASC ); // correct, works OK
原型: function SetWeights ( $weights )
按在索引中出现的先后顺序给字段设置权重。不推荐,请使用SetFieldWeights() 。
原型: function SetFieldWeights ( $weights )
按字段名称设置字段的权值。参数必须是一个hash(关联数组),该hash将代表字段名字
的字符串映射到一个整型的权值上。
字段权重影响匹配项的评级。 节 4.4, “ 权值计算 ” 解释了词组相似度如何影响评级。这个调用用于给不同的全文数据字段指定不同于默认值的权值。
给定的权重必须是正的32位整数。最终的权重也是个32位的整数。默认权重为1。未知的
属性名会被忽略。
目前对权重没有强制的最大限制。但您要清楚,设定过高的权值可能会导致出现32位整数
的溢出问题。例如,如果设定权值为10000000并在扩展模式中进行搜索,那么最大可能的
权值为10M(您设的值)乘以1000(BM25的内部比例系数,参见 节 4.4, “ 权值计算” )再
乘以1或更多(词组相似度评级)。上述结果最少是100亿,这在32位整数里面没法存储,
将导致意想不到的结果。
原型: function SetIndexWeights ( $weights )
设置索引的权重,并启用不同索引中匹配结果权重的加权和。参数必须为在代表索引名的字
符串与整型权值之间建立映射关系的hash(关联数组)。默认值是空数组,意思是关闭带权
加和。
当在不同的本地索引中都匹配到相同的文档ID时,Sphinx默认选择查询中指定的最后一个
索引。这是为了支持部分重叠的分区索引。
然而在某些情况下索引并不仅仅是被分区了,您可能想将不同索引中的权值加在一起,而不
是简单地选择其中的一个。SetIndexWeights()允许您这么做。当开启了加和功能后,最后的
匹配权值是各个索引中的权值的加权和,各索引的权由本调用指定。也就是说,如果文档
123在索引A被找到,权值是2,在B中也可找到,权值是3,而且您调用了
SetIndexWeights ( array ( "A"=>100, "B"=>10 ) ),那么文档123最终返回
给客户端的权值为2*100+3*10 = 230。
原型: function SetIDRange ( $min, $max )
设置接受的文档ID范围。参数必须是整数。默认是0和0,意思是不限制范围。
此调用执行后,只有ID在$min和$max(包括$min和$max)之间的文档会被匹配。
原型: function SetFilter ( $attribute, $values, $exclude=false )
增加整数值过滤器。
此调用在已有的过滤器列表中添加新的过滤器。$attribute是属性名。$values是整数数组。
$exclude是布尔值,它控制是接受匹配的文档(默认模式,即$exclude为假时)还是拒绝它
们。
只有当索引中$attribute列的值与$values中的任一值匹配时文档才会被匹配(或者拒绝,如
果$exclude值为真)
原型 : function SetFilterRange ( $attribute, $min, $max, $exclude=false )
添加新的整数范围过滤器。
此调用在已有的过滤器列表中添加新的过滤器。$attribute是属性名, $min、$max定义了
一个整数闭区间,$exclude布尔值,它控制是接受匹配的文档(默认模式,即$exclude为
假时)还是拒绝它们。
只有索引中$attribute列的值落在$min和$max之间(包括$min和$max),文档才会被匹配
(或者拒绝,如果$exclude值为真)。
原型: function SetFilterFloatRange ( $attribute, $min, $max, $exclude=false )
增加新的浮点数范围过滤器。
此调用在已有的过滤器列表中添加新的过滤器。$attribute是属性名, $min、$max定义了
一个浮点数闭区间,$exclude必须是布尔值,它控制是接受匹配的文档(默认模式,即
$exclude为假时)还是拒绝它们。
只有当索引中$attribute列的值落在$min和$max之间(包括$min和$max),文档才会被匹
配(或者拒绝,如果$exclude值为真)。
原型: function SetGeoAnchor ( $attrlat, $attrlong, $lat, $long )
为地表距离计算设置锚点,并且允许使用它们。
$attrlat和$attrlong是字符串,分别指定了对应经度和纬度的属性名称。$lat和$long是浮点值,指定了锚点的经度和纬度值,以角度为单位。
一旦设置了锚点,您就可以在您的过滤器和/或排序表达式中使用@geodist特殊属性。Sphinx将在每一次全文检索中计算给定经纬度与锚点之前的地表距离,并把此距离附加到匹配结果上去。SetGeoAnchor和索引属性数据中的经纬度值都是角度。而结果会以米为单位返回,因此地表距离1000.0代表1千米。一英里大约是1609.344米。
原型: function SetGroupBy ( $attribute, $func, $groupsort="@group desc" )
设置进行分组的属性、函数和组间排序模式,并启用分组(参考 节 4.6, “ 结果分组(聚类)中的描述)。
$attribute是字符串,为进行分组的属性名。$func为常数,它指定内建函数,该函数以前面
所述的分组属性的值为输入,目前的可选的值为:
SPH_GROUPBY_DAY, SPH_GROUPBY_WEEK, SPH_GROUPBY_MONTH,
SPH_GROUPBY_YEAR, SPH_GROUPBY_ATTR 。
$groupsort是控制分组如何排序的子句。其语法与 节 4.5, “SPH_SORT_EXTENDED 模式” 中
描述的相似。
分组与SQL中的GROUP BY子句本质上相同。此函数调用产生的结果与下面伪代码产生的
结果相同。
SELECT ... GROUP BY $func($attribute) ORDER BY $groupsort
注意,影响最终结果集中匹配项顺序的是$groupsort。排序模式(见 节 5.3.3,“SetSortMod e”)影响每个分组内的顺序,即每组内哪些匹配项被视为最佳匹配。比如,组之间可以根据
每组中的匹配项数量排序的同时每组组内又根据相关度排序。
Starting with version 0.9.9-rc2, aggregate functions (AVG(), MIN(), MAX(), SUM()) are supported through SetSelect() API call when using GROUP BY. 自从0.9.9-rc2开始,聚类函数(AVG(), MIN(), MAX(), SUM())也可通过SetSelect() 调用用于分组(GROUP BY)了。
原型: function SetGroupDistinct ( $attribute )
设置分组中需要计算不同取值数目的属性名。只在分组查询中有效。
$attribute是包含属性名的字符串。每个组的这个属性的取值都会被储存起来(只要内存允
许),其后此属性在此组中不同值的总数会被计算出来并返回给客户端。这个特性与标准
SQL中的COUNT(DISTINCT)子句类似。因此如下Sphinx调用
$cl->SetGroupBy ( "category", SPH_GROUPBY_ATTR, "@count desc" );
$cl->SetGroupDistinct ( "vendor" );
等价于如下的SQL语句:
SELECT id, weight, all-attributes,
COUNT(DISTINCT vendor) AS @distinct,
COUNT(*) AS @count
FROM products
GROUP BY category
ORDER BY @count DESC
在上述示例伪代码中,SetGroupDistinct()调用只与COUNT(DISTINCT vendor)对应。
GROUP BY,ORDER By和COUNT(*)子句则与SetGroupBY()调用等价。两个查询都会在每
类中返回一个匹配的行。除了索引中的属性,匹配项还可以包含每类的匹配项计数和每类中
不同vendor Id的计数。
原型: function Query ( $query, $index="*" )
连接到searchd服务器,根据服务器的当前设置执行给定的查询,取得并返回结果集。
$query是查询字串,$index是包含一个或多个索引名的字符串。一旦发生一般错误,则返回
假并设置GetLastError()信息。若成功则返回搜索的结果集。 Additionally, the contents of $comment are sent to the query log, marked in square brackets, just before the search terms, which can be very useful for debugging. Currently, the comment is limited to 128 characters.
$index的默认值是“*”,意思是对全部本地索引做查询。索引名中允许的字符包括拉丁字母
(a-z),数字(0-9),减号(-)和下划线(_),其他字符均视为分隔符。因此,下面的
示例调用都是有效的,而且会搜索相同的两个索引。
$cl->Query ( "test query", "main delta" );
$cl->Query ( "test query", "main;delta" );
$cl->Query ( "test query", "main, delta" );
给出多个索引时的顺序是有意义的。如果同一个文档ID的文档在多个索引中找到,那么权
值和属性值会取最后一个索引中所存储的作为该文档ID的权值和属性值,用于排序、过滤,
并返回给客户端(除非用SetIndexWeights()显式改变默认行为)。因此在上述示例中,索引
“delta”中的匹配项总是比索引“main”中的更优先。
如果搜索成功,Query()返回的结果集包含找到的全部匹配项中的一部分(根据SetLimits()之
设定)和与查询相关的统计数据。结果集是hash(仅PHP,其他语言的API可能使用其他数
据结构),包含如下键和值:
"matches":
是一个hash表,存储文档ID以及其对应的另一个包含文档权重和属性值的hash表(或者是数组,如果启用了SetArrayResult())。
"total":
此查询在服务器检索所得的匹配文档总数(即服务器端结果集的大小)。这是在当前设置下,用当前查询可以从服务器端获得的匹配文档数目的上限。
"total_found":
(服务器上找到和处理了的)索引中匹配文档的总数。
"words":
一个hash,它将查询关键字(关键字已经过大小写转换,取词干和其他处理)映射到一个包含关于关键字的统计数据(“docs”——在多少文档中出现,“hits”——共出现了多少次)的小hash表上。
"error":
searchd报告的错误信息(人类可读的字符串)。若无错误则为空字符串。
"warning":
searchd报告的警告信息(人类可读字符串)。若无警告则为空串。
It should be noted that Query() carries out the same actions as AddQuery() and RunQueries() without the intermediate steps; it is analoguous to a single AddQuery() call, followed by a corresponding RunQueries(), then returning the first array element of matches (from the first, and only, query.)
Prototype: function AddQuery ( $query, $index="*", $comment="" )
向批量查询增加一个查询。$query为查询串。$index为包含一个或多个索引名的字符串。$comment are sent to the query log, marked in square brackets, just before the search terms, which can be very useful for debugging. Currently, this is limited to 128 characters. 返回RunQueries()返回的数组中的一个下标。Additionally if provided, the contents of
批量查询(或多查询)使searchd能够进行可能的内部优化,并且无论在任何情况下都会减
少网络连接和进程创建方面的开销。相对于单独的查询,批量查询不会引入任何额外的开销。
因此当您的Web页运行几个不同的查询时,一定要考虑使用批量查询。
例如,多次运行同一个全文查询,但使用不同的排序或分组设置,这会使searchd仅运行一
次开销昂贵的全文检索和相关度计算,然后在此基础上产生多个分组结果。
有时您不仅需要简单地显示搜索结果,而且要显示一些与类别相关的计数信息,例如按制造
商分组后的产品数目,此时批量查询会节约大量的开销。若无批量查询,您会必须将这些本
质上几乎相同的查询运行多次并取回相同的匹配项,最后产生不同的结果集。若使用批量查
询,您只须将这些查询简单地组成一个批量查询,Sphinx会在内部优化掉这些冗余的全文搜
索。
AddQuery()在内部存储全部当前设置状态以及查询,您也可在后续的SubQuery()调用中改变
设置。早先加入的查询不会被影响,实际上没有任何办法可以改变它们。下面是一个示例:
$cl->SetSortMode ( SPH_SORT_RELEVANCE );
$cl->AddQuery ( "hello world", "documents" );
$cl->SetSortMode ( SPH_SORT_ATTR_DESC, "price" );
$cl->AddQuery ( "ipod", "products" );
$cl->AddQuery ( "harry potter", "books" );
$results = $cl->RunQueries ();
用上述代码,第一个查询会在“documents”索引上查询“hello world”并将结果按相关度排序,
第二个查询会在“products”索引上查询“ipod”并将结果按价格排序,第三个查询在“books”
索引上搜索“harry potter”,结果仍按价格排序。注意,第二个SetSortMode()调用并不会影
响第一个查询(因为它已经被添加了),但后面的两个查询都会受影响。
Additionally, any filters set up before an AddQuery() will fall through to subsequent queries. So, if SetFilter() is called before the first query, the same filter will be in place for the second (and subsequent) queries batched through AddQuery() unless you call ResetFilters() first. Alternatively, you can add additional filters as well.
This would also be true for grouping options and sorting options; no current sorting, filtering, and grouping settings are affected by this call; so subsequent queries will reuse current query settings.
AddQuery()返回RunQueries()返回的数组中的一个下标。它是一个从0开始的递增整数,即,
第一次调用返回0,第二次返回1,以此类推。这个方便的特性使你在需要这些下标的时候
不用手工记录它们。
原型: function RunQueries ()
连接到searchd,运行由AddQuery()添加的全部查询,获取并返回它们的结果集。若发生一
般错误(例如网络I/O失败)则返回假并设置GetLastError()信息。若成功则返回结果集的简
单数组。
该数组中的每一个结果集都跟Query()返回的结果集完全相同。注意,批量查询请求自身
几乎总是成功——除非有网络错误、正在进行索引轮换,或者其他导致整个查询无法被处理
的因素。
然而其中的单个的查询很可能失败。此时与之对应的结果集只包含一个非空的“错误”信息,
而没有关于匹配或查询的统计信息。在极端情况下,批量查询中的所有单个查询可能都失败。
但这仍然不会导致报告一般错误,因为API已经成功地连接到searchd,提交了批量查询并
得到返回结果——但每个结果集都只包含特定的错误信息。
原型: function ResetFilters ()
清除当前设置的过滤器。
通常此调用在使用批量查询的时候会用到。您可能需要为批量查询中的不同查询提供不同的
过滤器,为达到这个目的,您需要调用ResetFilters()然后用其他调用增加新的过滤器。
原型: function ResetGroupBy ()
清除现有的全部分组设置,并关闭分组。
通常此调用在使用批量查询的时候会用到。单独的分组设置可以用SetGroupBy()和
SetGroupDistinct()来改变,但它们不能关闭分组。ResetGroupBy()将之前的分组设置彻底重
置并在当前状态下关闭分组模式,因此后续的AddQuery()可以进行无分组的搜索。
原型: function BuildExcerpts ( $docs, $index, $words, $opts=array() )
该函数用来产生文档片段(摘要)。连接到searchd,要求它从指定文档中产生片段(摘
要),并返回结果。
$docs为包含各文档内容的数组。$index为包含索引名字的字符串。给定索引的不同设置
(例如字符集、形态学、词形等方面的设置)会被使用。$words为包含需要高亮的关键字的字符串。它们会按索引的设置被处理。例如,如果英语取词干(stemming)在索引中被设置为允许,那么即使关键词是“shoe”,“shoes”这个词也会被高亮。Starting with version 0.9.9-rc1, keywords can contain wildcards, that work similarly to star-syntax available in queries. $opts为包含其他可选的高亮参数的hash:
"before_match":
在匹配的关键字前面插入的字符串。默认为“<b>”
"chunk_separator":
在摘要块(段落)之间插入的字符串。默认为“...”
"limit":
摘要最多包含的符号(码点)数。整数,默认为256.
"around":
每个关键词块左右选取的词的数目。整数,默认为5.
"exact_phrase":
是否仅高亮精确匹配的整个查询词组,而不是单独的关键词。布尔值,默认为假。
"single_passage":
是否仅抽取最佳的一个段落。布尔值,默认为否。
失败时返回假。成功时返回包含有片段(摘要)字符串的数组。
原型: function UpdateAttributes ( $index, $attrs, $values )
立即更新指定文档的指定属性值。成功则返回实际被更新的文档数目(0或更多),失败则
返回-1。
$index为待更新的(一个或多个)索引名。$attrs为属性名字符串的数组,其所列的属性会
被更新。$values为hash表,$values表的键为文档ID,$values表的值为新的属性值的简单
数组。
$index既可以是一个单独的索引名,也可以是一个索引名的列表,就像Query()的参数。与
Query()不同的是不允许通配符,全部待更新的索引必须明确指出。索引名列表可以包含分
布式索引。对分布式索引,更新会同步到全部代理上。
只有在docinfo=extern这个存储策略下才可以运行更新。更新非常快,因为操作完全在内存
中进行,但它们也可以变成持久的,更新会在searchd干净关闭时(收到SIGTERM信号时)
被写入磁盘。With additional restrictions, updates are also possible on MVA attributes; refer to mva_updates_pool directive for details.
使用示例:
$cl->UpdateAttributes ( "test1", array("group_id"), array(1=>array(456)) );
$cl->UpdateAttributes ( "products", array ( "price", "amount_in_stock" ),
array ( 1001=>array(123,5), 1002=>array(37,11), 1003=>(25,129) ) );
第一条示例语句会更新索引“test1”中的文档1,设置“group_id”为456.第二条示例
语句则更新索引“products”中的文档1001,1002和1003。文档1001的“price”会
被更新为123,“amount_in_stock”会被更新为5;文档1002,“price”变为37而
“amount_in_storage”变为11,等等。
原型: function BuildKeywords ( $query, $index, $hits )
Extracts keywords from query using tokenizer settings for given index, optionally with per-keyword occurrence statistics. Returns an array of hashes with per-keyword information.
$query is a query to extract keywords from. $index is a name of the index to get tokenizing settings and keyword occurrence statistics from. $hits is a boolean flag that indicates whether keyword occurrence statistics are required.
Usage example:
$keywords = $cl->BuildKeywords ( "this.is.my query", "test1", false );
原型: function EscapeString ( $string )
转义被sphinx查询语言解析器认为是特殊字符的字符。返回转义过的字符串。
$string 是需要转义的字符串。
这个函数看上去可能是多余的,因为它可以在调用程序中实现。然而,由于特殊字符可能改变,这确保在所有情况下都有一个转义所有特殊字符的API调用。
例子:
$escaped = $cl->EscapeString ( "escaping-sample@query/string" );
原型: function Status ()
查询searchd运行状态,返回状态及值的数组。
例子:
$status = $cl->Status ();
foreach ( $status as $row )
print join ( ": ", $row ) . "\n";
持久连接允许在单一网络连结上执行多个命令,如果不这么用,需要重连多次。
原型: function Open ()
打开到服务器的持久连接。
原型: function Close ()
关闭先前打开的持久连接。
数据源类型。必须选项,无默认值。已知的类型包括mysql,pgsql,xmlpipe, xmlpipe2和odbc。所有其他与数据源相关的选项都依赖于这个选项指定的源类型。与SQL数据源(即MySQL和PostgreSQL)相关的选项以“sql_”开头,而与xmlpipe和xmlpipe2数据源相关的选项则以“xmlpipe_”开头。All source types except xmlpipe are conditional; they might or might not be supported depending on your build settings, installed client libraries, etc. mssql type is currently only available on Windows. odbc type is available both on Windows natively and on Linux through UnixODBC library.除了xmlpipe之外,所有的数据源类型都是有条件的;是否支持依赖于编译时的设置,已安装的客户端库等 。mssql类型仅能用于Windows。odbc类型在Windows上是有原生支持的,在Linux平台上需要UnixODBC库的支持。
示 例:
type = mysql
索引文件的路径和文件名(不包括扩展名)。必须选项。
path既包括文件夹也包括文件名,但不包括扩展名。indexer在产生永久和临时索引文件的最终名字时会附加上不同的扩展名。永久数据文件有几个不同的扩展名,都以“.sp”开头,临时文件的扩展名以“.tmp”开头。如果indexer没有成功地自动删除.tmp*文件,手工删除是安全的。
以下是不同索引文件所存储的数据种类,供参考:
.spa 存储文档属性(仅在extern_docinfo存储模式中使用)
.spd 存储每个词ID可匹配的文档ID列表
.sph 存储索引头信息
.spi 存储词列表(词ID和指向.spd文件的指针)
.spm 存储MVA数据
.spp 存储每个词ID的命中(或者说记账,或者词的出现)列表
.spk 未知文件格式类型。
.sps 存储索引的字段原文(>=0.9.10-dev)。
.spl 未知文件类型
示 例:
path = /var/data/test1
索引过程内存使用限制。可选选项,默认32M。
这是indexer不会超越的强制内存限制。可以以字节、千字节(以K为后缀)或兆字节(以M为后缀)为单位。参见示例。当过小的值导致I/O缓冲低于8KB时该限制会自动提高,此值的最低限度依赖于待索引数据的大小。如果缓冲低于256KB,会产生警告。最大可能的限制是2047M。太低的值会影响索引速度,但256M到1024M对绝大多数数据集(如果不是全部)来说应该足够了。这个值设得太高可能导致SQL服务器连接超时。在文档收集阶段,有时内存缓冲的一部分会被排序,而与数据库的通信会暂停,于是数据库服务器可能超时。这可以通过提高SQL服务器端的超时时间或降低mem_limit来解决。
示 例:
mem_limit = 256M
# mem_limit = 262144K # same, but in KB
# mem_limit = 268435456 # same, but in bytes
每秒最大I/O操作次数,用于限制I/O操作。可选选项,默认为0(无限制)。
与I/O节流有关的选项。它限制了每秒钟最大的I/O操作(读或写)的次数。值0意思是不
加限制。
indexer在索引时可能导致突发的密集磁盘I/O,因此需要限制它磁盘活动(给同一台机器上运行的其他程序留出一些资源,比如searchd)。I/O节流就是用来实现上述功能的。它的工作原理是,在indexer的连续磁盘I/O操作之间强制增加一个保证的延迟。现代SATA硬盘每秒钟可以执行多达70-100以上次的I/O操作(主要受磁头寻道时间的限制)。将索引I/O限制为上述数值的几分之一可以减轻由索引带来的搜索性能下降。
示例:
max_iops = 40
最大允许的I/O操作大小,以字节为单位,用于I/O节流。可选选项,默认为0(不限制)。与I/O节流有关的选项。它限制indexer文件I/O操作的单次最大大小。值0代表不加限制。超过限制的读写操作会被分成几个小的操作,并被max_iops 计为多次。在本文写作时,全部I/O操作都被限制在256KB以下(默认的内部缓冲大小),因此大于256KB的max_iosize值没有任何作用。
示例:
max_iosize = 1048576
允许XMLPipe2数据源中最大字段大小,以字节计,可选选项,默认是2MB。
例如:
max_xmlpipe2_field = 8M
写缓冲区大小,可选选项,默认是1MB。
Write buffers are used to write both temporary and final index files when indexing. Larger buffers reduce the number of required disk writes. Memory for the buffers is allocated in addition to mem_limit. Note that several (currently up to 4) buffers for different files will be allocated, proportionally increasing the RAM usage.
例如:
write_buffer = 4M
Dsfdsfdsfdsf
dsfdsf
WARNING: zero/NULL document_id, skipping 也就是Sphinx限制文档id>0,且不等于NULL, 这个要求是正常的,如果出现这个问题,产生数据源的部分有bug。
WARNING: no process found by PID 4066.
WARNING: indices NOT rotated.
indexer命令创建或者更新索引时,在seachd没有运行的时候错误使用了 –rotate参数。
需要仔细检测searchd是否正在运行。
Is it better to set a numeric attribute to NULL or use zero?
The added new record has weight higher than other record?
Extreme slowness within BuildExcerpts?做文档摘要的时候非常慢?
5个排序属性够 不够用?
还有一个BM25F算法更高级些,Sphinx会实现它吗?目前还没有。
配置文件支持include吗?不支持,但是,如果sphinx.conf的第一行以#!开始的话,sphinx把它当作脚本执行,执行的输出作为sphinx的配置。通过这个功能,可以使用perl,php,sh脚本写一个类似include的动态配置文件。
分类的更改合并如何做。
索引更新间隔分为分种级,小时级,天级,如何实现?
区间搜索对性能的影响如何? 没有问题,效果很好。参见6.4.3. SetFilterRange
客户端与服务器端的通信协议?
Sphinx不能搜索数字吗? 支持,但必须完全匹配的数据才能搜索到。像在文本中有一段12345,那么搜索12345有结果,但搜索1234则没有结果。
Sphinx数据库数据源中的字段如果有NULL值,sphinx是怎么处理的。如果是字符串字段,要做分词索引的情况,则null与空字符串''一样,Sphinx认为它不会匹配为任何查询,除了全扫描模式。数据源的字段没null,即使是索引用的属性字段,创建或者更新索引也不会有问题。
Sphinx支持不同字段数的源放在同一个索引中吗?不支持,不同的表要想放在同一索引中,必须抽象为一张表。
searchd的cache缓存如何实现,效果如何?
如何把字段原文放在索引文件中,查询的时候一起查询出来?
在0.9.9中使用sql_attr_str2ordinal作为一个属性存储在索引的属性文件中(.spa),这个字段的长度限制为4K。也就是说,目前只能存储标题了,如果描述不超过4K的话也可以这么存储,但对内存的要求非常高的。
上面这个sql_attr_str2ordinal的理解错误,这个属性的目的是做字段串排序用的,在做完索引之后,其实这个值转换成了一个整数了,最后返回的值也是个整数了,而不是这个字符串字段的原文。
在0.9.10-dev中,新加配置选项,sql_field_string, sql_attr_string, 这些字段的原文存储在一个新的索引文件中(.sqs), 这个还很不稳定,可以创建,但查询的时候出错。
Sphinx支持精确匹配吗?如果只有这一个条件的话,可以使用短语匹配(SPH_MATCH_PHRASE)。这样sphinx把查询字符串当作一个短语执行完全精确匹配。
但是有一个问题,如果这个需要的精确匹配只是在某个字段上需要,其他字段需要使用的扩展匹配,这个应该如何处理?
支持多少索引字段? 32个
支持多少个属性?参见下面一个,不会小于max_filters的值吧。
支持多少个过滤条件?这个是可配置的,在配置文件中有max_filters,默认256。每个过滤条件中允许的最大数值个数也是可配置的,配置选项为max_filter_values,默认为4096,内部用比较多,外部调用很少需要这个值。
searchd的架构?多进程架构,为每个连接分配一个进程。不断分配新的连接会造成服务器频繁的创建进程。这些进程之间是否有共享的内存,如果没有,则连接数越多,用的系统内存资源越多。
如何加快searchd的启动时间?由于默认情况下,searchd启动会预加载部分索引数据到内存,速度比较慢,几十秒到几分种不等,与数据量有直线关系,这个有没有方法改善?
Sphinx 0.9.10-dev中.sps文件要全部加载到内存,怎么样不让这个加载到内存,会有什么影响?
如何查询空字段,非空字段?在字段索引时做些判断,多加一个是否空属性。
如何按照文档ID执行查询?将文档ID起个别名,把这个作为一属性存储。是否有方法直接在ID上过滤呢,这样可能更好?
如何能在api调用查询后得到完整的查询语句,类似SQL语句一样?日志中有,但如何通过API取得呢?
2010.1.23 1.10.x的实时更新索引,还不支持字符串属性, 现有属性和0.9.9的索引功能差不多。更新必须使用SPHINXQL语句(类SQL语句),没有API调用更新。Realtime index要用到的workers = threads还会导致searchd崩溃。
Sort on BOTH EXPRESSION and ATTRIBUTE? Use setSelect to create your expression as a virtual attribute, then you can use it your sort clause.