使用来自巨大 select 的数据的大 INSERT 性能

performance of big INSERT with data from huge select

我们正在为商店生成一些交叉销售数据。我们想要显示像 "customers who looked at this product, also looked at these products" 这样的东西。 为了生成此数据,我们每天从基于会话的产品查看数据中执行此查询。

            INSERT INTO
                product_viewed_together
            (
                product,
                product_associate,
                viewed
            )
            SELECT
                v.product,
                v2.product,
                COUNT(*)
            FROM
                product_view v
            INNER JOIN
                product_view v2
            ON
                v2.session = v.session
                AND v2.product != v.product
                AND DATE_ADD(v2.created, INTERVAL %d DAY) > NOW()
            WHERE
                DATE_ADD(v.created, INTERVAL %d DAY) > NOW()
            GROUP BY
                v.product,
                v2.product;

Table product_view 连接到自身。由于此 table 相当大(大约 2600 万行),因此结果更大。查询发出大量的性能和时间。

我不会用,我们选择了一个很好地解决问题的布局。有没有更好的方法来存储和生成这些数据?

进行日期测试可搜索:

DATE_ADD(v.created, INTERVAL %d DAY) > NOW()

-->

v.created > NOW - INTERVAL %d DAY

product_viewVIEW 吗?还是一个TABLE?如果是table,提供两个"covering"索引:

INDEX(created, session, product)  -- (for v)
INDEX(session, created, product)  -- (for v2)

也许你得到的所有计数都是甚至?这个错误可以通过大约 3 种方式修复,每种方式都会使速度加倍。我认为最佳的方法是将 ON 中的 one 行更改为

DATE_ADD(v2.created, INTERVAL %d DAY) > NOW()

-->

v2.created > v.created

我认为这会使速度加倍。

但是,如果您可以拥有两个具有相同 created 的不同产品,则计数可能不完全正确。

另一个问题:你最终会得到

prod  assoc  CT
123   234    43
234   123    76  -- same pair, opposite order

我修改后的测试表明 234 出现在 123 之前的频率高于其他方式。

试试看。但如果你还需要更多;我还有一个更具侵略性的想法。