MySQL-按许多类别(许多行...)搜索产品的速度更快?

时间:2018-09-23 08:18:55

标签: mysql sql inner-join

我有大量的数据集(即每个表2千万行),看起来像是这样(我不是真正在处理产品和类别,但情况相同)

餐桌产品

public class FriendsHolder extends RecyclerView.ViewHolder {
    @BindView(R.id.name)
    TextView textName;
    @BindView(R.id.image)
    CircleImageView imageView;
    @BindView(R.id.title)
    TextView textTitle;
    @BindView(R.id.company)
    TextView textCompany;
    @BindView(R.id.latitude)
    TextView textLatitude;
    @BindView(R.id.longitude)
    TextView textLongitude;

    public FriendsHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);

    }
}

以及类别表

|id|name|created_at|
--------------------
|1 |....|2018-06...|
|2 |....|2018-06...|
|3 |....|2018-06...|
|4 |....|2018-06...|
|5 |....|2018-06...|
...etc.

我想做的是搜索,以查找具有多个类别的产品。

|id|product_id|category|description|
------------------------------------
|1 |1         | abc    | def       |
|2 |1         | ghi    | jkl       |
|3 |1         | mno    | pqr       |
|4 |2         | abc    | stu       |
|5 |2         | wvx    | yz        |
...etc

但这真的很慢...我对此尝试了不同的方法,但是每个人至少要花30秒。

我已经建立了用于连接的列的索引。

因此,基本上,我想在产品必须匹配一个或多个类别的情况下进行搜索。另外,稍后,我要进行搜索,以使产品与类别和描述匹配(可能来自类别表中的不同行)。

有什么想法吗?或者也许是链接,在这里我可以阅读更多有关此类案例的信息?

3 个答案:

答案 0 :(得分:2)

临时表应该有助于加快处理速度。

CREATE TEMPORARY TABLE tmpCategories( category_id INT)

找到一种方法,将要搜索的类别的ID插入此表中。

然后编写类似于以下内容的联接:

SELECT p.* FROM product p
INNER JOIN categories c ON p.product_id = c.product_id
INNER JOIN tmpCategories tc ON tc.catrgory_id = c.category_id

您的查询可能不完全是这样。但是这种方法可以加快速度。

P.S。我正在用手机打字,请原谅::

答案 1 :(得分:1)

第一个建议是您可以在子查询上使用INNER JOIN而不是IN

    SELECT DISTINCTROW * 
    FROM product p 
    INNER JOIN  (
        SELECT categories.product_id FROM categories WHERE category = 'abc'
    ) t1 on p.id  = t1.product_id
    INNER JOIN (
        SELECT categories.product_id FROM categories WHERE category = 'ghi'
    ) t2 on p.id = t2.product_id
    INNER JOIN (
        SELECT categories.product_id FROM categories WHERE category= 'mno'
    ) t3 p.id = t3.product_id
    WHERE  'some extra where' 

    ORDER BY product.created_au LIMIT 10 offset 0

您还可以尝试使用单个子查询来获取所有具有3类的product_id

    SELECT DISTINCTROW * 
    FROM product p 
    INNER JOIN  (
       SELECT categories.product_id FROM categories WHERE category IN ( 'abc','ghi', 'mno')
       group by categories.product_id 
       having count(distinct category ) = 3
    ) t1 on p.id  = t1.product_id
    WHERE  'some extra where' 

    ORDER BY product.created_au LIMIT 10 offset 0

如果内部联接无法按预期的速度加速,则请确保类别表上的复合索引正确

 CREATE INDEX index_name  ON categories(category,product_id );

答案 2 :(得分:0)

我只会使用GROUP BYHAVING来获得产品:

select c.product_id
from categories c
where c.category in ('abc', 'ghi', 'mno')
group by c.product_id
having count(*) = 3;

您可以使用joinexistsin来获取其余产品信息:

select p.*
from products p join
     (select c.product_id
      from categories c
      where c.category in ('abc', 'ghi', 'mno')
      group by c.product_id
      having count(*) = 3
     ) cp
     on c.product_id = p.i
where . . .  -- other conditions on product