优化SQL查询

时间:2018-09-03 05:18:42

标签: php mysql sql query-optimization

在非常简单的情况下,我遇到了一个有趣的问题。 我在MySQL数据库中有帖子和用户表。帖子可以被用户喜欢。 因此,有一个单独的表,称为Likes,该表具有以下列:user_idpost_id

当用户在应用程序中点击“ like”按钮时,将执行对php脚本的请求。脚本正在检查表中是否存在post_id和user_id与请求信息匹配的行。用户对某条信息的赞不能超过1个,如果我按一下已喜欢的信息,则以前的赞应该会消失

我现在使用2个查询: 1)检查表中是否存在 2)如果记录不存在-我将其添加,如果存在,则将其删除。

现在,我发现表格中来自同一用户的同一条帖子有两次赞。似乎单个用户的两个请求几乎可以立即执行。

我如何优化它-因此不可能从用户的一篇帖子中添加两个赞?我认为我需要改为运行单个查询,但是应该是什么?

3 个答案:

答案 0 :(得分:3)

很明显,您的插入/更新部件被多次触发。您应该调查为什么会发生这种情况,然后尽可能避免这种情况。

由于有多个调用,因此多次询问DBMS是否存在该条目。对于所有电话,答案是否定的。然后触发多个插入,您将获得重复。因此,在SQL方面,有两件事出错了:

  1. 为什么甚至可以为同一帖子和用户插入多个记录?应该提供一个主键或唯一键,以使之不可能。

我认为这对于您的数据模型是必须的。

  1. 操作顺序错误。可能的解决方案是先插入(一个将成功,其他将失败-当然提供了上述密钥!),并且在失败时将发布更新。但是,MySQL甚至可以一步一步实现:

ON DUPLICATE KEY

insert into likes (post_id, user_id, like_date)
 values (@post_id, @user_id, current_date)
 on duplicate key update like_date = current_date;

答案 1 :(得分:0)

使用InnoDB,然后

START TRANSACTION;
SELECT ... FOR UPDATE;
if it does not exist
    INSERT ...;
else
    DELETE ...
COMMIT;

通过使用事务语义,您可以避免多个连接彼此踩踏的任何问题。我想我什至避免了任何死锁的机会。

答案 2 :(得分:-1)

只需使用一个标志(值为0或1的列),并更新该值而不删除整个行。

您的步骤应如下:

  1. 检查行是否存在。
  2. 如果存在,则更新列(例如-1,不同于-0)

就是这样。

在模板中检查0或1是否表示