#mysql #optimization #select
#mysql #оптимизация #выберите
Вопрос:
Я использую mysql для обновления поля в таблице при выполнении условия…
Должен ли я сначала выполнить SELECT, чтобы увидеть, выполнено ли условие, или я просто пытаюсь использовать UPDATE каждый раз, потому что, если условие не выполнено, ничего не происходит.
Чтобы быть конкретным, вот мой ВЫБОР:
SELECT * FROM forum_subscriptions
WHERE IDTopic=11111 AND IDUser=11111 and status=0
Я проверяю здесь, нахожусь ли я в теме форума 11111, и если, если я (идентификатор пользователя 1) подписан на эту тему и мой статус подписки равен 0 (это означает, что он еще не получил электронное письмо о новой публикации в теме)
Итак, когда это выполнено, сделайте:
UPDATE forum_subscriptions SET Status=1 where IDTopic=11111 AND IDUser=1
Теперь мне интересно, я всегда выбираю здесь, чтобы запросить, подписан ли пользователь на эту тему, и у него есть статус, что он посещал эту тему раньше, поэтому любые новые сообщения не будут вызывать новое уведомление по электронной почте. Когда он снова посещает страницу, запускается обновление, которое сбрасывает посещение, поэтому любые новые сообщения снова будут отправлять ему электронное письмо.
Таким образом, для каждого пользователя выбирается, подписан он или нет на тестирование подписки. Обновление производится только при необходимости.
Лучше ли просто использовать обновление? Пытаться обновлять на каждой странице, если он не подписан на тему, это ничего не обновит.
Как быстро выполняется обновление, которое не выдает никаких достоверных данных? Как это делается внутренне, как update находит, есть ли какая-либо запись, выбирает ли она, а затем обновляет? Если это так, было бы лучше только обновить, потому что я бы добился того же самого без каких-либо замедлений. Если обновление дороже, чем select, я должен попытаться сначала проверить, а затем обновить при необходимости.
Этот пример является примером из реальной жизни, но логика, лежащая в основе этого обновления / выбора, действительно меня интересует, потому что я чаще сталкиваюсь с такого рода проблемами.
Спасибо
ОБНОВЛЕНИЕ: Спасибо обоим ребятам, но я не вижу по вашим ссылкам, блокируется ли обновление даже без результатов или нет. Поскольку вы дали разные ответы, я все еще не знаю, что делать.
Таблица подписки действительно не обязательно должна быть myisam, я мог бы изменить ее на InnoDB, потому что у меня нет необходимости вводить в нее полный текст. Это хорошее решение — использовать только update и изменить эту маленькую таблицу на inno? Есть ли у смешивания типов таблиц какие-либо недостатки?
Комментарии:
1. Вы спрашиваете относительно таблиц
InnoDB
илиMyISAM
?2. Я использую таблицы MyISAM, но, думаю, я мог бы использовать эту таблицу подписки в качестве INNODB, поскольку мне не нужен полнотекстовый текст в ней… Разумно ли менять его на innodb и использовать только update?
Ответ №1:
Вы просто выполняете обновление, без предварительного выбора:
UPDATE forum_subscriptions SET Status=1 where IDTopic=11111 AND IDUser=1
Если условия не выполнены, обновление ничего не сделает.
Это обновление выполняется очень быстро, если у вас есть индекс на status
и IDtopic
и IDuser
!
Пустое обновление выполняется так же быстро, как и пустой select.
Если вы сначала выполните select, вы просто замедлите работу без причины.
Если вы хотите знать, сколько строк, где обновлено, выполняют
SELECT ROW_COUNT() as rows_affected
После выполнения обновления это сообщит вам 0, если ни одна строка не была обновлена, или количество обновленных строк (или вставленных или удаленных, если вы использовали эти инструкции).
Эта функция сверхбыстрая, потому что ей нужно всего лишь извлечь одно значение из памяти.
Обходные пути для проблем с блокировкой таблицы
Смотрите здесь: http://dev.mysql.com/doc/refman/5.5/en/table-locking.html
Комментарии:
1. Большое спасибо, так что само обновление, если сначала сделать выбор, чтобы увидеть, обновляется ли вообще? Я имею в виду, что пользователи, которые не являются подписчиками, на самом деле не блокируют таблицу myisam из-за этого заявления об обновлении?
2. Где мне выбрать ROW_COUNT()? Сразу после ОБНОВЛЕНИЯ? Что, если между обоими запросами произошло другое обновление?
3. Спасибо за обновление. Но если бы в mysql произошло какое-то другое ОБНОВЛЕНИЕ где-нибудь на сайте, я бы получил неправильный ROW_COUNT()?
4. @Jerry2, row_count() — это значение для каждого сеанса. Если у вас есть 100 сеансов подключения к базе данных, row_count вернет только количество строк, затронутых запросами обновления / удаления / вставки, которые ВЫ инициировали в СВОЕМ сеансе. и только строки, затронутые в вашем последнем запросе.
5. Ага, я вижу, тогда все в порядке. Он всегда будет возвращать правильное значение. Мне не нужен ROW_COUNT (), но приятно узнать решение.
Ответ №2:
Потенциальным побочным эффектом постоянного вызова UPDATE
является блокировка, которую необходимо установить, чтобы гарантировать, что никакое другое соединение не изменяет эти строки.
- Если таблица является
MyISAM
— блокировка будет установлена на всю таблицу во время поиска. - Если таблица является
InnoDB
, блокировки будут размещены на индексах / пробелах.
Из документов:
Блокирующее чтение, ОБНОВЛЕНИЕ или УДАЛЕНИЕ обычно устанавливают блокировки записей для каждой индексной записи, которая сканируется при обработке инструкции SQL. Не имеет значения, есть ли в инструкции условия WHERE, которые исключали бы строку
Комментарии:
1. Таким образом, блокировка выполняется, даже если результат пустой, что происходит большую часть времени? Теперь действительно возникает вопрос о том, как выполняется обновление инстернально в mysql 5.6. Сначала выбирается и, если находит запись, обновляется или просто пытается обновить и заблокировать, даже если записей нет.
2. @jerry2 Да. Если вы используете
InnoDB
таблицы и у вас есть соответствующие индексы, это не должно быть проблемой.3. Блокировки @jerry2 устанавливаются во время поиска записей, которые необходимо обновить.
4. @Jerry2: видишь dev.mysql.com/doc/refman/5.5/en/internal-locking.html для получения информации о том, как работает блокировка hwo.
5. Я использую MyISAM, потому что мне нужен полнотекстовый поиск. Так что, лучше использовать select и update только по мере необходимости?