Sphinx vs. MySql - 搜索朋友列表(效率/速度)

Won*_*nka 15 mysql indexing search sphinx

我正在将我的应用程序移植到MySQL的Sphinx中,并且很难解决这个问题,或者甚至需要移植它(我真的想知道是否值得使用sphinx这个特定的效率案例来提高效率/速度):

users
uid uname
  1    alex
  2    barry
  3    david

friends
uid | fid
  1     2
  2     1
  1     3
  3     1
Run Code Online (Sandbox Code Playgroud)

细节是:
- InnoDB
- 用户: uid上的索引,uname上的索引
- 朋友: uid上的组合索引,fid

通常,使用mysql搜索所有alex的朋友:

$uid = 1
$searchstr = "%$friendSearch%";
$query = "SELECT f.fid, u.uname FROM friends f 
          JOIN users u ON f.fid=u.uid
          WHERE f.uid=:uid AND u.uname LIKE :friendSearch";
$friends = $dbh->prepare($query);
$friends->bindParam(':uid', $uid, PDO::PARAM_INT);
$friends->bindParam(':friendSearch', $searchstr, PDO::PARAM_STR);
$friends->execute();
Run Code Online (Sandbox Code Playgroud)

使用sphinx vs mysql找到alex的朋友是否更有效率,或者这会是一种矫枉过正?
如果sphinx会更快,因为列表会让成千上万的人看到,索引查询会是什么样子?我如何删除与sphinx不再存在的友谊,我可以在这种情况下有一个详细的例子吗?我应该更改此查询以使用Sphinx吗?

Sam*_*aye 7

好的,这就是我看到这个工作的方式.

我和MongoDB有完全相同的问题.MongoDB"提供"搜索功能,但就像MySQL一样,你不应该使用它们,除非你想要被IO,CPU和内存问题所困扰,并被迫使用更多的服务器来处理你的索引.

如果使用Sphinx(或其他搜索技术),整个想法是通过拥有一个高性能的索引搜索器来降低每台服务器的成本.

但是Sphinx不是存储引擎.查询表之间的确切关系并不是那么简单,他们已经使用SphinxQL重新调整了一点,但是由于全文索引的性质,它仍然没有像在MySQL中那样进行整体连接.

相反,我会将关系存储在MySQL中,但在Sphinx中有一个"用户"索引.

在我的网站上我个人有2个索引:

  • main(包含用户,视频,频道和播放列表)
  • 帮助(帮助系统搜索)

这些是每分钟更新一次的delta.由于实时索引有时仍然是有点实验性的,我个人已经看到了高插入/删除率的问题,我保持delta增量更新.因此,我将使用delta索引来更新我的站点的主要可搜索对象,因为这比实时索引(来自我自己的测试)的资源密集程度更低,性能更高.

请注意,为了处理删除以及您的Sphinx集合不通过delta,您需要一个killlist和delta索引的某些过滤器.这是我的索引中的一个例子:

source main_delta : main
{
    sql_query_pre = SET NAMES utf8
    sql_query_pre =
    sql_query = \
        SELECT id, deleted,  _id, uid, listing, title, description, category, tags, author_name, duration, rating, views, type, adult, videos, UNIX_TIMESTAMP(date_uploaded) AS date_uploaded \
        FROM documents \
        WHERE id>( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 ) OR update_time >( SELECT last_index_time FROM sph_counter WHERE counter_id=1 )

    sql_query_killlist = SELECT id FROM documents WHERE update_time>=( SELECT last_index_time FROM sph_counter WHERE counter_id=1 ) OR deleted = 1
}
Run Code Online (Sandbox Code Playgroud)

这会每分钟处理一次删除和添加,这对于真实的Web应用程序来说几乎是实时的.

所以现在我们知道如何存储我们的索引.我需要谈谈这些关系.Sphinx(尽管它有SphinxQL)不会对数据进行整体连接,所以我个人建议在Sphinx之外做一个关系,不仅如此,但正如我所说的这种关系表将获得高负载所以这可能会影响到狮身人面像指数.

我会查询所有ID并使用这组ID使用sphinx API上的"filter"方法将主索引过滤到特定的文档ID.完成后,您可以正常搜索Sphinx.这是迄今为止我发现的最有效的方法.

在任何时候都要记住的关键是Sphinx是一种搜索技术,而MySQL是一种存储技术.记住这一点,你应该没问题.

编辑

正如@NB所说(在我的回答中我忽略了)Sphinx确实有SphinxSE.虽然它是开发性的并且仍然处于其开发的测试阶段(与实时索引相同),但它确实为Sphinx提供了一个实际的MyISAM/InnoDB类型存储.这太棒了.但是有一些警告(与任何事情一样):

  • 语言是主要的
  • 连接是主要的

但它可以/可以完成你想要的工作,所以一定要调查一下.


Pet*_*gad 6

所以我要继续前进,并总结一下 - 我觉得狮身人面像的最佳用例是什么,你可以决定它是否或多或少符合你的目标.

如果您要做的只是字符串搜索一个字段; 然后使用MySQL,你可以毫不费力地进行外卡搜索,并且可以使用索引,除非你期望数百万行你没事.

现在拿facebook,这不仅是索引名称,而是页面等甚至任何高级搜索字段.Sphinx可以从MySQL,PostGRES,MongoDB中获取x列(在此处插入您想要的数据库)并在所有这些列中创建可搜索的全文索引.

例:

您有5个字段(门牌号,街道,城市,州,邮政编码),您希望对所有这些字段进行全文搜索.现在使用MySQL你可以对每一个进行搜索,但是使用sphinx你可以将它们全部联合起来然后sphinx根据你传入的字符串以及由它产生的匹配来做一些很棒的统计结果.

这个链接:PHP Sphinx Searching可以很好地指导您查看它的外观以及它们如何协同工作.

所以你并没有真正取代数据库; 你只需要添加一个特殊的守护进程(sphinx),它允许你创建专门的索引并对它运行全文搜索.


Shl*_*ach 5

没有索引可以帮助您解决此查询,因为您正在寻找字符串作为中缀,而不是前缀(您正在寻找'%friendname%',而不是'friendname%'.

此外,LIKE解决方案将让您陷入困境:假设您正在寻找一位名叫Ann的朋友.LIKE表达式也将与Marianne,Danny等相匹配.表达式中没有"完整的单词"概念LIKE.

一个真正的解决方案是使用文本索引.一个FULLTEXT指数只有上可用MyISAM,和MySQL 5.6(不GA在这个时候)将推出FULLTEXTInnoDB.

否则你确实可以使用Sphinx来搜索文本.

只有几百或几千,你可能看不到很大的区别,除非你真的要做每秒多次搜索.数字越大,您最终会发现全表扫描不如Sphinx搜索.

我正在使用Sphinx很多,有几十甚至数亿个大文本,并且可以证明它有点像魅力.

当然,Sphinx的问题在于它是一个外部工具.使用Sphinx,您必须告诉它从数据库中读取数据.您可以crontab每隔5分钟,每小时等(例如使用)这样做.因此,如果行是DELETEd,则只有在下次从表中读取数据时才会从sphinx中删除它们.如果你能忍受 - 那是最简单的解决方案.

如果不能,sphinx中有实时索引,因此您可以直接指示它删除某些行.我无法解释此端口中的所有内容,因此以下是一些链接:

索引更新

实时索引

最后的结论是,您有三种选择:

  1. 冒险并使用全表扫描,假设您没有高负荷.
  2. 等待MySQL 5.6FULLTEXT与InnoDB一起使用.
  3. 使用狮身人面像

在这个时候,我肯定会使用选项#3:使用sphinx.