对于这个系统来说,什么是更好的解决方案查询


What's a better solr query for this system?

我聘请了一位数据库顾问,他一直建议使用solr来处理我当前完全mysql系统的全文搜索方面,以加快通常很慢的搜索速度(每次搜索最多30秒)。

他/我们的大部分时间都花在了 a) 调整 mysql 设置以挤出额外的性能,以及 b) 安装 solr。然而,现在我们的时间接近尾声,前几个 solr 测试查询似乎正在失败。

首先,这是我当前完全Mysql设置的相关3个表,以及我们试图用MySQL/Solr方法替换的完全MySQL查询。然后是我们正在测试的 Solr 查询。

TABLE1 - 存储全文搜索记录的主表。它们由 songID 列、艺术家列和标题列组成。索引 - 歌曲 ID 主、艺术家全文

(非唯一)、艺术家树(非唯一)、标题全文(非唯一)、标题树(非唯一)

表2 - 用于存储DJ歌曲列表。它引用上表的 ID。一些 DJ 有 150,000+ 首歌曲,因此这里有 150,000+ 行引用 TABLE1 中的歌曲。TABLE2 还有一个 ID 列和一个歌曲版本列(命名版本),因此 DJ 可以将自己的版本引用应用于同一首歌曲的多个版本(即同一首歌曲的多行,每行都有不同的版本数据)。索引 - ID primary, djID btree (non unique), songID btree (non unique).

TABLE3 - 一个标记映射表,其中包含对 TABLE2 中 ID 的引用,以及标记的 ID(在另一个名为 TAGS 的表中)。它存储TABLE2中每首歌曲的流派,语言,十年的标签,加上DJ可以有多个歌曲列表(标记List1,List2等),因此引用每首歌曲所属的歌曲列表。每个 DJ 最多可以有大约 12 个标签,每首歌曲最多可以有大约 12 个标签。索引 - rowID primary、ID btree (非唯一)、tag_id(非唯一)

这是当前针对艺术家关键字"披头士"的 mysql 搜索查询,唯一涉及的标签是告诉我们只选择 DJ 33 的 List1 中歌曲的匹配项:

"SELECT t1.*, t2.version 
FROM  table1 t1, table2 t2, tagmap tm, tag t
WHERE MATCH (t1.Artist) AGAINST ('+beatles* ' IN BOOLEAN MODE) 
AND tm.tag_id = t.tag_id
AND (t.name IN ('List1'))
AND t2.ID = tm.ID
AND t2.songID = t1.songID
AND t2.djID = '33'
GROUP BY t2.ID
HAVING COUNT( tm.tag_id )=1
ORDER BY t1.Artist, t1.Title ASC LIMIT {$lastRowNum},{$limit1}";// pagination blah

它可以工作,但在大于 5000 的列表上,它很慢。

他提出的SOLR解决方案:

  • 为 TABLE1 中的歌曲制作 solr 索引
  • 搜索过程中,在 mysql 中查询 TABLE2 以获取属于相关 DJ 的歌曲 ID
  • 在艺术家上为关键字创建一个 solr 查询,并将 DJ 的歌曲 ID 注入其中......

    .../solr/select/?q=id:(3688804 3688807)和艺术家:披头士&wt=json

(我省略了 url,以及空格和括号,因此在这里很容易查看,但它们在工作代码中被 %20 等替换)

上面这个只有 2 首歌曲 ID 的示例似乎有效,但在测试中,一旦您开始向其中添加大约 1000 多首歌曲 ID,查询就会失败。考虑到一些 DJ 有 150,000+ 首歌曲,因此可能有 150,000+ 首唯一歌曲 ID 注入 solr 查询,这似乎是一个有缺陷的解决方案。

另外,我不知道标签将如何进入查询过程。

感谢您的观看。

我建议您使用 Solr,但实现方式略有不同。

您的所有数据库规范化都非常适合事务系统(即添加歌曲、创建播放列表等)

搜索在非规范化数据结构上效果最好。您可以创建一个表示搜索结果的 Solr 架构,并使用 SQL 查询填充它。

查询仍然效率低下,但它不需要在每次搜索时运行(即实时)。相反,您可以每晚批量填充索引,并在歌曲/播放列表等更改时进行涓流增量更改。

我在这里写了一些东西。希望这有帮助。