【问题标题】:query for what customers have bought together with the listed product查询客户与列出的产品一起购买了什么
【发布时间】:2010-06-28 10:58:53
【问题描述】:

我正在尝试优化一个我无法理解的非常古老的查询。我要归档的结果是,我想在网上商店向访问者推荐其他客户感兴趣的东西,即他们与访问者正在查看的产品一起购买的其他产品。

我有一个子查询,但它非常很慢,大约需要 15 秒处理大约 8 000 000 行。

布局是所有放入用户购物篮的产品都保存在表wsBasket 中,并由basketid 分隔(在另一个表中与成员相关联)。

在本例中,我想列出用户购买的所有最受欢迎的产品以及 productid 427,但不列出 productid 427 本身。

SELECT productid, SUM(quantity) AS qty 
FROM wsBasket 
WHERE basketid IN 
    (SELECT basketid 
     FROM wsBasket 
     WHERE productid=427) AND productid!=427 
GROUP by productid 
ORDER BY qty 
DESC LIMIT 0,4;

非常感谢任何帮助!希望这对至少某人有任何意义:)

 

更新 1: 感谢你们的 cmets 伙计们,这是我的答案,他们不适合 cmets-field。

在上面的查询中使用 EXPLAIN,我得到了结果。请注意,我的表上没有任何索引(id 字段上的主键除外),我想修改查询以从索引中受益并将索引放在正确的键上。

+----+--------------------+----------+------+---------------+------+---------+------+------+----------------------------------------------+
| id | select_type        | table    | type | possible_keys | key  | key_len | ref  | rows | Extra                                        |
+----+--------------------+----------+------+---------------+------+---------+------+------+----------------------------------------------+
|  1 | PRIMARY            | wsBasket | ALL  | NULL          | NULL | NULL    | NULL | 2821 | Using where; Using temporary; Using filesort |
|  2 | DEPENDENT SUBQUERY | wsBasket | ALL  | NULL          | NULL | NULL    | NULL | 2821 | Using where                                  |
+----+--------------------+----------+------+---------------+------+---------+------+------+----------------------------------------------+

【问题讨论】:

  • wsBasket 表上有哪些索引?当您对查询执行 EXPLAIN 时会得到什么?
  • 您的索引是什么样的?知道这可能会更容易帮助您修改查询。

标签: mysql subquery webshop


【解决方案1】:

要添加两个明显的索引:一个在 basketid 上,第二个在 productid 上:然后重试查询和一个新的 EXPLAIN 以查看索引正在被使用

【讨论】:

  • 成功了,现在查询约为 0.124! :) 我正在研究组合索引并修改查询。谢谢!有什么办法可以避免子查询?
  • 组合/复合索引可能对针对此表的其他查询有用,但只有您知道执行了哪些其他类型的查询,所以如果没有更多信息,我们将无能为力......但我怀疑这两个简单的索引也将有助于应用程序代码的其他领域
  • 查看 bobince 修改查询的响应
【解决方案2】:

除了确保在 productidbasketid 上存在合适的索引外,您通常还可以从将查询构造为简单的连接而不是子查询中受益,尤其是在 MySQL 中。

SELECT b1.productid, SUM(b1.quantity) AS qty
FROM wsBasket AS b0
JOIN wsBasket AS b1 ON b1.basketid=b0.basketid
WHERE b0.productid=427 AND b1.productid<>427
GROUP BY b1.productid
ORDER BY qty DESC
LIMIT 4

对我来说,在一个可能相似的数据集上,连接导致EXPLAIN 输出中有两个select_type: SIMPLE 行,而子查询方法吐出一个性能糟糕的DEPENDENT SUBQUERY。因此,连接速度大大提高了一个数量级。

【讨论】:

    【解决方案3】:

    您在此查询中主要用于搜索的两个字段是 productid 和 basketid。

    当您搜索 productid 等于 427 的记录时,数据库不知道在哪里可以找到该记录。它甚至不知道如果它确实找到了一个匹配项,就不会再有另一个匹配项,因此它必须查看整个表,可能有数千条记录。

    索引是一个单独的已排序文件,仅包含您对排序感兴趣的字段。因此创建索引可以节省大量时间!

    【讨论】:

      猜你喜欢
      • 2013-09-05
      • 2021-12-13
      • 1970-01-01
      • 2020-07-30
      • 2022-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多