2014-01-04 3 views
0

Предположим, у меня есть таблица пользователей с 1M пользователей MySQL/InnoDB:InnoDB и count: Помогают ли столы-помощники?

пользователей

  • идентификатор пользователя (первичный ключ, Int)
  • статус (Int)
  • больше данных

Если бы я хотел иметь точный подсчет количества пользователей с status = 1 (обозначая активацию учетной записи), каким будет путь для больших таблиц, я был думать вдоль линий:

usercounts

  • статус
  • Количество

А затем запустить TRIGGER AFTER INSERT на users, который обновляет наши правила столбцов в usercounts

ли это быть лучший способ пойти?

пс. Дополнительный небольшой вопрос: Так как вы нуждаетесь в TRIGGER AFTER UPDATE на users для того, когда status изменений, есть синтаксис, который может:

  • охватывает как TRIGGER AFTER INSERT и TRIGGER AFTER UPDATE на status?
  • Добавляет count к одному, если count уже есть, еще вставляет новую пару (status, count = 0)?
+0

Как часто строки быть сгенерированные/обно в таблице 'users'? Каковы допустимые значения статуса? Только '0' и' 1' или есть другие? – peterm

+0

@peterm Это просто концептуальный пример, но примером может быть статус: 1 = ok, 2 = deleted, 3 = banned. И вставки будут происходить только раз в то время, обновления, однако, будут происходить довольно много, но не в самом поле 'status'. – skiwi

ответ

1

Будет ли это лучший способ пойти?

Лучшее (основанное на мнениях) или нет, но это определенно возможный путь.

существует ли синтаксис, который может: охватывает как триггер AFTER INSERT и UPDATE TRIGGER ПОСЛЕ о статусе?

Нет. В MySQL нет составного триггерного синтаксиса. Вам придется создавать отдельные триггеры.

есть синтаксис, который доступен: увеличивает значение счетчика на единицу, если граф уже присутствует, то вставляет новый (статус, Count = 0) пару?

Да. Вы можете использовать предложение ON DUPLICATE KEY в заявлении INSERT. Убедитесь, что status является ПК в таблице usercounts.

Теперь, если пользователи могут быть удалены, даже если они предназначены только для технического обслуживания, вам также необходимо закрыть его с помощью AFTER DELETE триггера.


Это сказанное ваши триггеры могут выглядеть как

CREATE TRIGGER tg_ai_users 
AFTER INSERT ON users 
FOR EACH ROW 
    INSERT INTO usercounts (status, cnt) 
    VALUES (NEW.status, 1) 
    ON DUPLICATE KEY UPDATE cnt = cnt + 1; 

CREATE TRIGGER tg_ad_users 
AFTER DELETE ON users 
FOR EACH ROW 
    UPDATE usercounts 
     SET cnt = cnt - 1 
    WHERE status = OLD.status; 

DELIMITER $$ 
CREATE TRIGGER tg_au_users 
AFTER UPDATE ON users 
FOR EACH ROW 
BEGIN 
    IF NOT NEW.status <=> OLD.status THEN -- proceed ONLY if status has been changed 
    UPDATE usercounts 
     SET cnt = cnt - 1 
    WHERE status = OLD.status; 
    INSERT INTO usercounts (status, cnt) VALUES (NEW.status, 1) 
    ON DUPLICATE KEY UPDATE cnt = cnt + 1; 
    END IF; 
END$$ 
DELIMITER ; 

Для первоначально заселить использование usercounts таблица

INSERT INTO usercounts (status, cnt) 
SELECT status, COUNT(*) 
    FROM users 
GROUP BY status 

Вот это SQLFiddle демо

+0

Есть ли причина, по которой в моей базе данных (пользователи 10K) она иногда принимает 0,03, но иногда 4 секунды ? Или причина будет где-то в общем веб-хостинге. – skiwi

+0

Последовательные результаты обновления 100 случайных записей: 0.03s, 0.3s, 0.98s, 0.07s, 0.20s, 0.82s, 0.09s. Может быть, база данных? – skiwi

+0

Для дальнейшего использования вы можете объяснить, что «НЕ x <=> у меня есть, я просто понял это для себя, хотя – skiwi

0

Я думаю, что для вас доступны более простые варианты.

Просто добавьте индекс в поле, на которое вы хотите рассчитывать.

ALTER TABLE пользователи ADD KEY (статус);

Теперь выбор должен быть очень быстрым.

SELECT COUNT (*) FROM пользователей, где статус = 1

+0

Я видел случаи в течение нескольких часов, когда такой синтаксис на немного более сложной таблице стоил моих запросов около 0,4 с, я думаю, что «COUNT (*)» является основным виновником здесь, ссылка на другой вопрос: http://stackoverflow.com/questions/20924951/mysql-with-innodb-how-to-avoid-using-count/20925021 – skiwi

Смежные вопросы