Сценарий 1. Я ожидаю, что обновление счетчика 'view' (или 'click' или 'like' или что-то еще) будет больше похоже на
UPDATE t SET views = views + 1 WHERE id = 123;
Я предполагаю, что у вас есть индекс (возможно, PRIMARY KEY
) на id
?
Поскольку с этой таблицей происходят другие вещи, может быть целесообразно разделить быстро увеличивающийся счетчик на отдельную таблицу. Это позволит избежать вмешательства в другие запросы. Вы можете получить другие данные, плюс счетчик, используя JOIN .. USING(id)
.
Сценарий 2 не имеет смысла. Кажется, для каждого письма сохраняется самая последняя дата, но что означает country
? Поскольку это кажется больше, чем просто счетчик, вы можете захотеть, чтобы отдельная таблица регистрировала эти 3 столбца.
Пожалуйста, укажите SHOW CREATE TABLE
.
Есть много вещей, которые новички воспринимают как " CRA sh». Пожалуйста, опишите подробнее - нет подключений, недостаточно места на диске, медлительность, клиент выдал сообщение об ошибке, другие операции заняли слишком много времени и т. Д. c. У каждого есть свое лекарство.
Запрос
Вы в настоящий момент логически делаете
BEGIN;
$ct = SELECT views ... FOR UPDATE;
...
UPDATE ... SET views = $ct+1 WHERE ...;
COMMIT;
Если это так, это гораздо менее эффективно, чем
(with autocommit = ON)
UPDATE ... SET views = views+1 ...;
Обратите внимание, что первая версия дольше висит на строке. Если вам не удастся использовать FOR UPDATE
, вы потеряете некоторые значения.
Разделение на отдельную таблицу заставляет вас запускать UPDATE
как свою собственную транзакцию.
Другое
innodb_flush_log_at_trx_commit
:
- По умолчанию установлено значение 1, которое является безопасным, но приводит к как минимум одному IOP для каждой транзакции.
- 2 отведения гриппу sh раз в секунду. В напряженные времена это гораздо эффективнее. Но Cra sh может потерять до одной секунды обновлений. неточность «количества просмотров» из-за редкого cra sh, на мой взгляд, приемлема.
KEY(views)
необходимо обновлять каждый раз, когда views
изменяется. Но благодаря «буферу изменений» это вряд ли потребует каких-либо дополнительных операций ввода-вывода, по крайней мере сейчас, когда вы выполняете UPDATE
.
INT(1)
занимает 4 байта; (1)
не имеет смысла. Рекомендуется изменить значение на TINYINT
(1 байт), сэкономив при этом около 27 байт на строку. (7 столбцов плюс 2 индекса)
country INT(1)
- Это флаг? В чем смысл? Нормализовано ли это к другой таблице? Использование 4 байтов для идентификатора и дополнительной таблицы, когда стандартные сокращения («США», «Великобритания», «RU», «IN» и т. Д. c) заняли бы 2 байта? Предлагайте country CHAR(2) CHARACTER SET ascii COLLATE ascii_general_ci
.
Индексирование флагов редко приносит пользу. Давайте посмотрим на запросы, где вы думаете, такие индексы могут быть использованы. И EXPLAIN SELECT ...
для них.