繁体   English   中英

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

[英]SQL count many-to-many values or have it counted every time new row is added?

我正在使用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表,该表将描述用户添加项目的时间

  • 将一个ts DATETIME列添加到users表中,该表将描述实际情况,只要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表中计算得更快,并且您不会经常更新记录时出现并发问题。

您应该首先索引user_items.item_id并对其进行分组而不是名称。 字符串分组要慢得多(自己试试),索引应该加快速度。 如果仍然太慢,您可以首先运行GROUP BY查询,然后如果您的DBMS执行计划默认情况下没有这样做,则可以加入项目表。

该查询几乎每次都进行全表扫描。 没有办法解决这个问题。 索引会加快我加速连接的速度,但随着数据的增长,查询会变得越来越慢。

存储摘要数据,如“计数”和“项目”将是要走的路。 您可以使用存储过程或代码执行此操作。 作为双重检查,您可以定期(即每天一次)更新所有计数,以便您知道它们是准确的。

我的冲动是将数据保留为正常形式(换句话说,不增加“计数”字段),然后在应用程序级别缓存慢查询的结果。

如果缓存无效,因为许多人正在进行查询,而且很少有人进行两次,那么,是的,您可以设置一个存储过程来自动更新某些表中的某些行。 详细信息因数据库供应商而异。 这是在Postgresql中如何做到这一点 由于竞争条件,这是唯一安全的方法(即在DB内,而不是从应用程序层)。

每次运行查询时,您真的获得了36,000名用户吗? 如果您正在寻找性能问题的根源,那么它可能就在那里。

根据您的RDBMS,您可以查看索引或物化视图等内容。 将计数作为表的一部分并尝试维护它几乎肯定是一个错误,特别是对于数据库的小尺寸。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM