在H2中有效地从多对多关系中进行选择

时间:2011-08-11 11:15:23

标签: mysql sql many-to-many h2

我正在使用H2,我有一个书籍数据库(表条目)和作者(表人员),通过多对多关系连接,本身存储在表Authorship中。 数据库相当大(900'000 +人和2.5M +书)。

我正在尝试有效地选择由至少一位名称与模式匹配的作者(LIKE'%pattern%')创作的所有书籍的列表。这里的诀窍是模式应该严格限制匹配作者的数量,每个作者都有相当少量的相关书籍。

我尝试了两个问题:

SELECT p.*, e.title FROM (SELECT * FROM Persons WHERE name LIKE '%pattern%')  AS p
  INNER JOIN Authorship AS au ON au.authorId = p.id
  INNER JOIN Entries AS e ON e.id = au.entryId;

SELECT p.*, e.title FROM Persons AS p
  INNER JOIN Authorship AS au ON au.authorId = p.id
  INNER JOIN Entries AS e ON e.id = au.entryId
WHERE p.name like '%pattern%';

我预计第一个会快得多,因为我正在加入一个更小的(子)作者表,但是他们都需要花费很长时间。事实上,我可以手动将查询分解为三个选项,然后更快地找到我想要的结果。

当我尝试EXPLAIN查询时,我发现它们确实非常相似(表上的完全连接,只有WHERE子句),所以我的问题是:如何实现快速选择,依赖于作者的过滤器应该导致与其他两个表的连接小得多吗?

请注意,我尝试使用MySQL进行相同的查询,并得到符合我预期的结果(首先选择更快)。

谢谢。

3 个答案:

答案 0 :(得分:1)

好的,这件事最终对我有用。

而不是运行查询:

SELECT p.*, e.title FROM (SELECT * FROM Persons WHERE name LIKE '%pattern%') AS p
  INNER JOIN Authorship AS au ON au.authorId = p.id
  INNER JOIN Entries AS e ON e.id = au.entryId;

......我跑了:

SELECT title FROM Entries e WHERE id IN (
  SELECT entryId FROM Authorship WHERE authorId IN (
    SELECT id FROM Persons WHERE name LIKE '%pattern%'
  )
)        

它不是完全相同的查询,因为现在我没有将作者ID作为结果中的列,但这样做我想要的:利用模式限制的事实作者的数量非常小,只能通过少量条目进行搜索。

有趣的是,这对于H2来说效果很好(比连接快得多),但是对于MySQL来说它非常慢。 (这与LIKE'%pattern%'部分无关,请参阅其他答案中的注释。)我认为查询的优化方式不同。

答案 1 :(得分:0)

无论你做什么,

SELECT * FROM Persons WHERE name LIKE '%pattern%'总是会在900,000+行表上使用LONG,因为当你的模式'%pattern%'% MySql开头时,不能使用任何索引而应该这样做全表扫描。你应该研究full-text indexes and function

答案 2 :(得分:0)

好吧,因为类似条件以通配符开头,所以会导致全表扫描总是很慢,不会发生内部缓存。

如果你想进行全文搜索,mysql不是你最好的选择。查看其他软件(例如solr)来解决此类问题。