Оптимизировать запросы SQL - PullRequest
0 голосов
/ 03 сентября 2018

Я столкнулся с интересной проблемой в очень простом случае. У меня есть сообщения и таблица пользователей в базе данных MySQL. Посты могут понравиться пользователям. Таким образом, есть отдельная таблица с названием «Нравится», в которой есть столбцы: user_id, post_id.

Когда пользователь нажимает кнопку «Мне нравится» в приложении, выполняется запрос к php-скрипту. Скрипт проверяет, есть ли в таблице строка, в которой post_id и user_id соответствуют информации из запроса. Пользователь не может иметь более 1 записи в сообщении, и если я нажму кнопку «Нравится» в уже добавленном сообщении, предыдущая запись должна исчезнуть

Сейчас я использую 2 запроса: 1) проверить, чтобы существовать в таблице 2) Если запись не существует - я добавляю ее, а если она существует, я удаляю ее.

Теперь я вижу, что в моей таблице встречаются двойные лайки одного и того же пользователя от одного и того же пользователя. Кажется, что два запроса от одного пользователя могут быть выполнены практически мгновенно.

Как я могу его оптимизировать - чтобы было невозможно добавить два лайка к одному сообщению от пользователя? Я думаю, что вместо этого мне нужно выполнить один запрос, но каким он должен быть?

Ответы [ 3 ]

0 голосов
/ 03 сентября 2018

Очевидно, что ваша вставка / обновление запускается несколько раз. Вам следует выяснить, почему это происходит, и, по возможности, предотвратить это.

Из-за нескольких вызовов СУБД несколько раз запрашивают, существует ли запись. Ответ - нет на все звонки. Затем несколько вставок запускаются, и вы получаете дубликаты. Таким образом, на стороне 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;
0 голосов
/ 13 сентября 2018

Используйте InnoDB, затем

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

Используя семантику транзакций, вы избегаете любых проблем, связанных с несколькими подключениями друг к другу. Я думаю, что я даже избежал любой возможности тупика.

0 голосов
/ 03 сентября 2018

просто используйте флаг (столбец со значением 0 или 1) и обновите значение, не удаляя всю строку.

Ваши шаги должны быть следующими:

  1. проверка существования строки.
  2. если существует, обновить столбец (например, - 1, в отличие от - 0)

Вот и все.

в шаблонах отметьте 0 или 1 для непохожих и похожих

...