0

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

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

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

TABLE1 - 存储全文搜索记录的主表。它们由 songID 列、Artist 列和 Title 列组成。INDEXES - songID primary、Artist Fulltext(非唯一)、Artist btree(非唯一)、Title Fulltext(非唯一)、Title btree(非唯一)

TABLE2 - 用于存储 DJ 歌曲列表。它引用了上表的 ID。一些 DJ 有 150,000 多首歌曲,因此这里有 150,000 多行引用表 1 中的歌曲。TABLE2 也有一个 ID 列,加上一个歌曲版本列(命名版本),因此 DJ 可以将自己的版本引用应用于同一首歌曲的多个版本(即同一首歌曲的多行,每行具有不同的版本数据)。INDEXES - ID primary,djID btree(非唯一),songID btree(非唯一)。

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

这是艺术家关键字“beatles”的当前 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
  • 为 Artist 上的关键字创建一个 solr 查询,并将 DJ 的歌曲 ID 注入其中...

    .../solr/select/?q=id:(3688804 3688807) AND 艺术家:beatles&wt=json

(我留下了网址,还有空格和括号,所以在这里很容易查看,但它们在工作代码中被替换为 %20 等)

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

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

谢谢参观。

4

1 回答 1

1

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

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

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

查询仍然是低效的,但它不需要在每次搜索时都运行(即实时)。相反,您可以每晚批量填充索引,并在歌曲/播放列表等发生变化时进行滴流变化。

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

于 2013-10-25T04:41:43.587 回答