SQL 计算多对多值还是每次添加新行时都计算?

标签 sql mysql count many-to-many

我正在使用 MySQL (MyISAM) 5.0.41 并且我有这个查询:

SELECT `x`.`items`.id, `x`.`items`.name, COUNT(*) AS count
    FROM `x`.`items` INNER JOIN `x`.`user_items`
    ON `x`.`items`.id = `x`.`user_items`.item_id
    GROUP BY name HAVING count > 2 ORDER BY count DESC

我有大约 36,000 个用户、175,000 个 user_items 和 60,000 个不断添加的项目。所以这个查询有点慢......

是否更好:

  • items 中有一个 count 字段并定期更新(比如每次用户添加一个项目时)
  • 或像这样(慢慢地)运行查询..

或者是否有任何 SQL 可以为我填充计数字段?

谢谢

最佳答案

您可以使用中间解决方案:

  • ts DATETIME 列添加到 user_items 表,该列将描述用户添加项目的时间

  • users 表中添加一个 ts DATETIME 列来描述实际情况,只要 cnt,缓存计数列

  • 使用新的计数和时间戳定期更新 users 表:

    INSERT
    INTO    users (id, ts, cnt)
    SELECT  *
    FROM    (
            SELECT  user_id, NOW() AS nts, COUNT(*) AS ncnt
            FROM    user_items ui
            WHERE   ui.timestamp <= NOW()
            )
    ON DUPLICATE KEY
    UPDATE  ts = nnow,
            cnt = ncnt
    
  • 删除 user_items 条目时使用户的时间戳无效

  • 发出此查询以计算项目数:

    SELECT  u.id, u.cnt +
            (
            SELECT  COUNT(*)
            FROM    user_items ui
            WHERE   ui.ts > u.ts
                    AND ui.user_id = u.id
            )
    FROM    users
    

这样,user_items 表中只会计算新添加的项目,速度要快得多,而且您不会因为过于频繁地更新记录而遇到并发问题。

关于SQL 计算多对多值还是每次添加新行时都计算?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2148005/

相关文章:

SQL:对下一列使用 case 表达式中的值

mysql - on 子句中的未知列 {0}

SQL Server : how to create a table from a pivot table?

sql - 为什么使用 '*' 构建 View 不好?

mysql - SQL 按受欢迎程度排序?

php - 使用 currancy 格式的字段将 CSV 导入 MYSQL

mysql - 如何在没有关系的情况下通过枢轴选择将表与其自身连接?

java - 重复数字

c# - 如何将 MySql 的返回数据分配给 C# 变量?

mysql - 计算来自一个 SQL 查询的不同数据