php - 使用 Sphinx/MySQL 一次从两个表中获取数据有更好的方法吗?

标签 php mysql sphinx

在问这个问题之前,了解我实际上在做什么很重要。

与我正在实现的功能相比,最好的比较是 Facebook 的搜索功能。当您开始输入时,会出现一个包含各种搜索结果的下拉列表。在顶部,您会找到名字与您的搜索匹配的 friend ,然后是其他匹配的人,然后是页面、事件等....

我的情况类似,但我只想搜索两件事。用户和文档(在下面的代码中命名为涟漪)。

我有这个工作正常。在我讨论我的案例中此功能的逻辑时,请耐心等待:

  1. 用户专注于搜索输入。
  2. Ajax 请求检索登录的用户 friend /关注者/关注者并将它们缓存在客户端(这仅在用户第一次关注搜索输入时发生)
  3. 随着用户的输入,一个高度优化的函数会针对用户名数组执行正则表达式,并构建一个包含头像等的自动完成列表...
  4. 同时,每次按键都会向下面的脚本发出 ajax 请求,该脚本执行以下操作:

    • 对两个单独的索引执行两个单独的 Sphinx 搜索。一个收集用户 ID,另一个收集文档 ID (rippleid)
    • 用户查询的结果通过检查在 ajax 请求中发送的用户 ID 数组来循环,以避免重复在初始高速 friend /关注者检查期间已经显示的用户。
    • 接下来我们查询实际数据库以获取剩余用户标识的用户数据
    • 然后重复相同的过程,但这次是针对文档(涟漪)

最后,所有返回的结果都会附加到自动完成列表中。

这是执行 sphinx 查找并从数据库中获取数据的 PHP 函数示例。

         public function search()
                {
                                $this->disableLayout();
                                $request = new Request();
                                $params = $request->getParams(GET);

//Perform sphinx textsearch include('/usr/local/lib/php/sphinxapi.php'); $sphinx = new \SphinxClient(); $sphinx->setMatchMode(SPH_MATCH_ANY); $sphinx->SetLimits(0, 4); $mysqlconn = mysql_connect("127.0.0.1:9306") or die ("Couldn't connect to MySQL."); $users = $sphinx->Query($params['data']['q'], "users"); $ripples = $sphinx->Query($params['data']['q'], "ripples"); /* *USERS */ //Loop through users and only collect ID's that are not already present if (!empty($users["matches"])) { $ids = ""; foreach($users['matches'] as $id => $data) { if($ids > ""){ $ids .= ","; } if(!isset($params['data']['e'][$id])){ $ids .= $id; } } //If there any any remaining ID's collect the data from the database and return as JSON if(!empty($ids)){ $userdataquery = "select users.userid, users.firstname, users.lastname from tellycards_user_data users where userid IN($ids) "; $query = new Query($userdataquery); $usersoutput = $query->fetchAll(); } } /* *RIPPLES */ //Loop through ripples and collect ID's if (!empty($ripples["matches"])) { $rippleids = ""; foreach($ripples['matches'] as $id => $data) { if($rippleids > ""){ $rippleids .= ","; } $rippleids .= $id; } //If there any any remaining ID's collect the data from the database and return as JSON if(!empty($rippleids)){ $rippledataquery = "select ripples.id, ripples.name, ripples.screenshot from tellycards_ripples ripples where id IN($rippleids) "; $query = new Query($rippledataquery); $ripplesoutput = $query->fetchAll(); } } header('Content-type: text/json'); echo json_encode(array( 'users' => (!empty($usersoutput)) ? $usersoutput : null, 'ripples' => (!empty($ripplesoutput)) ? $ripplesoutput : null ));

您可能会问为什么我们要进行初始好友查找而不是对所有内容都使用 sphinx。那么通过执行上面的方法。由于在客户端存储了 friend 数组,因此用户在键入时会得到即时反馈,尽管 sphinx 的速度非常快,但由于 http 请求,不可避免地会出现一些延迟。在实践中,它的效果非常好,顺便说一下,它似乎也是 facebook 使用的方法。

还有很多 javascript 代码可以防止不必要的查找,返回的数据被添加到缓存堆等,以便将来的搜索不需要点击 sphinx/db 等......

现在终于到了我的实际问题....

当前的服务器端功能让我很困扰。现在有两个搜索由 Sphinx 执行,两个搜索由 MySQL 执行。我怎么可能将所有这些整理成一个 sphinx 查询和一个 MySQL 查询?有什么办法吗? (请记住,文档和用户可能共享相同的 PK ID,因为它们位于 MySQL 中的两个完全不同的表中,并且(当前)分布在两个单独的索引中)。或者有什么方法可以组合这两个 MySQL 查询,使它们比有两个单独的选择更有效?

或者……由于查询的简单性,我最好像上面那样将它们分开吗? (都是索引主键查询)

我想我要的是任何建议/建议。

非常欢迎任何评论。

最佳答案

如果没有两个 MySQL 查询,你真的无法逃脱。好吧,您可以通过使用 UNION 将它们合并为一个。或者通过创建一个新的组合“表”( View 或物化 View )——但真的不认为它值得付出努力。两个查询非常好-正如您所说的那样,它们已编入索引。

您可以使用一个 sphinx 索引(以及一个搜索查询)- 通过创建一个新的组合索引。因为你说你的 key 不是唯一的,所以必须创建一个新的合成 key 。

例如...

sql_query = SELECT userid*2 AS id, 1 AS table_id, firstname AS one, lastname as two FROM tellycards_user_data \
              UNION \
            SELECT (id*2)+1 as id, 2 AS table_id, name AS one, screenshot AS two FROM tellycards_ripples
sql_attr_unit = table_id

这为您提供了一个假键,以及一个用于标识结果来自哪个表的属性。您可以使用它来获取它来自的原始表。 (还有许多其他方法可以做同样的事情)

这允许您运行一个查询,可以获得合并的结果。

...但不相信这是个好主意。因为如果结果不对称,您可能会错过结果。假设一个表有 20 个匹配结果,另一个表有 10 个。假设您显示前 10 个结果,现在由于限制,第二个表的结果很可能隐藏在第一个表的下面(极端示例,实际上,希望它们混合在一起)。两个单独的查询,允许您保证从每个表中获得一些结果。

...毕竟如此。坚持你得到的。没关系。

关于php - 使用 Sphinx/MySQL 一次从两个表中获取数据有更好的方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12857931/

相关文章:

mysql - Oracle 11g 对比 MySQL 对比 Hadoop :- benchmarking for 10^6 to 10^9 records

mysql - 在现有字段上使用 If sum 条件更新新列

indexing - 如何利用Sphinx多索引提升性能

javascript - 发送表单而不显示结果

php - 复制到临时表需要很长时间

mysql - 使用 WHERE 和 BETWEEN 对两列进行排序

mysql - 使用 MySQL 5.7 运行 Sphinx 2.2.11 不起作用

php - 使用 * 标记列

php - 如何用 Delphi 和 PHP 获得相同的 MD5?

php - SPHINX 搜索引擎上的 enable_star 不工作