为慢速搜索引擎获取许多客户投诉 - 这是理所当然的。
我有一个数据库搜索引擎,我对如何进行搜索的最后一部分感到有些困惑,我需要以良好的性能运行。如果用户搜索某些单词,则最多可能需要一分钟才能执行。
解释我的设置;我有一个名为 my_table 的表格,带有可搜索的项目条目。这些项目有一个名为 linked_list 的列,其中包含指向表 linked_list 中 id (主要索引)的指针。
linked_list 列 id ,父,值
my_table 中的行可以指向 linked_list 中的任何 id ,以及特定列表中的任何位置。 (没有列表超过7个链接深)
我需要允许用户搜索 linked_list 中的值。所以我目前这样做的方法是首先搜索用户查询的 linked_list ,如下所示:
SELECT id FROM linked_list WHERE value LIKE '%query%'
在我得到所有结果后,我将它们变成了一个带有php的 id 数组,如下所示:{2516,8645,235,4,665,...}
然后我将这些数组项中的每一个都给它自己的" WHERE .. IN .."如下所示,并将它们组合在一起。
您可以想象,如果我在 linked_list 中有超过4个值匹配,则搜索会变得不合理。
SELECT * FROM my_table
WHERE
(((1108 in (linked_list_id,
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = linked_list_id),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ))))
OR ((2791 in (linked_list_id,
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = linked_list_id),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ))))
....
在你告诉我之前,只需将整个链表存储在my_table"中,这是不合理的。 linked_list可能会改变,它将成为维护的噩梦。
我已经考虑过使用Union,Join,HAVING .. IN ..但是没有任何工作。我会感激任何可以帮助我解决这个问题的人!谢谢!
---编辑--- 这是一些示例数据。
id | linked_list_id
--------------------
1 | 1000
2 | 1050
3 | 1234
4 | 1001
5 | 1000
6 | 1600
id | parent | value |
--------------------------------
1000 | 0 | A | (This is the root of one linked list)
1001 | 1000 | B |
1050 | 1600 | C |
1234 | 0 | D | (This is the root of another linked list)
1500 | 1000 | E |
1600 | 1001 | AA |
(所以这个数据的结构是:)
1050 -> 1600 -> 1001 -> 1000 -> 0
1500 ---^ |
1234 ---^
注意:我拥有的最长链表是7个节点深。这受到应用程序的限制,因此他们很可能不会超过7个节点。
所以,如果我搜索
SELECT id FROM linked_list WHERE value LIKE '%A%'
我得到了
{1000,1600}
然后当我运行长查询时,它看起来像这样:
SELECT id FROM my_table
WHERE
(((1000 in (linked_list_id,
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = linked_list_id),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ))))
OR ((1600 in (linked_list_id,
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = linked_list_id),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ),
(SELECT @last_parent:=`parent` FROM `linked_list` WHERE `id` = @last_parent ))))
....
我希望返回的结果是
{1,2,4,5,6}
因为这些行中的每一行都在其链接列表中的某处包含%A%。
希望这有帮助。
答案 0 :(得分:1)
所以我自己解决了这个问题。
对于这可能有所帮助的人,我做了以下事情。
1)我首先查询 linked_list 以查找%query%的任何匹配项,并将结果写入ID数组,如(1,2,3,4)
2)我递归查询 linked_list 以获取其父项在上面的ID数组中的所有CHILDREN,并将结果附加到ID数组。
3)然后在我的主 my_table 搜索查询中,我只是说
'... HAVING `linked_list_id` IN (1,2,3,4,5,6,7,...)'