【问题标题】:Search a many to many relationship with a wild card, performance issues使用通配符搜索多对多关系,性能问题
【发布时间】:2013-04-28 23:23:22
【问题描述】:

我正在为一个应用程序构建一个数据库,并且我正在一个更大的数据集上测试性能问题。我生成了大约 250,000 条位置记录。每个位置可以分配给许多类别,一个类别可以分配给许多位置。我的数据集为每个位置分配了 2-4 个类别。

我希望允许用户通过使用通配符搜索过滤哪些类别应该允许来搜索位置。因此,也许我想将所有类别与其中的“红色”一词进行匹配。因此,如果我输入红色,现在它会显示所有类别标题中包含“红色”的位置。另外,我想用相同的字符串通配符搜索位置标题。

我编写了一个有效的查询,但在大型数据集中性能很差。本质上,我使用的是内部查询,如果设置了限制并且我可以快速找到结果(大约 0.05 毫秒),这很好。如果我没有立即找到任何结果,它看起来像是遍历整个数据库并且查询大约需要 9-10 秒。

这是我的数据库的简化布局:

locations: id | title | address
categories: id | title
locations_categories: id | location_id | category_id

这是我目前使用的查询:

SELECT `id`,`title`,`address`
FROM (`locations`)
WHERE title LIKE '%string%'
AND WHERE id IN (
 SELECT location_id 
 FROM locations_categories 
 JOIN categories ON categories.id = locations_categories.category_id 
 WHERE categories.title LIKE '%string%')

【问题讨论】:

    标签: mysql sql scalability


    【解决方案1】:

    首先,你的主查询只是使用子查询的值,所以可以重写:

     SELECT location_id 
     FROM locations_categories 
     JOIN categories ON categories.id = locations_categories.category_id 
     WHERE categories.title LIKE '%string%'
    

    但我建议将此查询一分为二——对于大型数据集来说,JOIN 很慢。第一个将获得必要的类别 ID(带分页):

    SELECT id
    FROM categories
    WHERE title LIKE '%string%' LIMIT BY <start>, <step>
    

    然后就可以获取locations_categories:

    SELECT location_id FROM locations_categories WHERE category_id IN (...)
    

    您将使用您拥有的位置 ID 来检索相应的记录:

    SELECT * FROM locations WHERE id IN (...)
    

    这 3 个查询组合起来会比原来的查询快得多。

    此外,请确保您的标题列已编入索引——它可能是瓶颈。但由于您在搜索词的开头有一个通配符,因此您必须在此处使用 FULLTEXT 索引。

    【讨论】:

    • 我喜欢您第二个解决方案中的方法。我应该提一下,您的第一个解决方案可能不起作用,因为我在位置上的 SELECT 实际上将包含比 ID 更多的内容,因为我可能还会在位置部分添加 WHERE 过滤器。我已经更新了我的问题以反映。
    【解决方案2】:

    您的解释计划将确认(或反驳)这一点,但我怀疑您的问题是子句中的前导 %

    WHERE categories.title LIKE '%string%' 
    

    WHERE title LIKE '%string%`
    

    强制全表扫描。要解决这个问题,通常需要了解相关领域和应用程序

    简单的方法是只搜索“开始于”。其他包括全文搜索、基于函数的索引、具有预先排序和列出已知搜索的相关记录的“分组表”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-16
      • 2013-09-30
      • 2015-10-29
      • 2019-05-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多