Предположим, у меня есть очень большая итоговая таблица, в которой мы храним сумму баллов активности, строку для каждого пользователя, для каждого дня и сумму активности - для каждого типа, отдельного столбца - который пользователь сделал в тот день.:
CREATE TABLE summry_data
(
UserID INT NOT NULL,
ActivityDate DATE,
t1 INT NOT NULL,
t2 INT NOT NULL,
t3 INT NOT NULL,
t4 INT NOT NULL,
PRIMARY KEY(UserID, ActivityDate)
)
Каждое утро мы заполняем данные предыдущего дня.мы вставляем строку для каждого пользователя:
INSERT summery_data
SELECT UserID, '2010-12-16'
, SUM(IF(TypeID = 1, Points, 0))
, SUM(IF(TypeID = 2, Points, 0))
, SUM(IF(TypeID = 3, Points, 0))
, SUM(IF(TypeID = 4, Points, 0))
FROM activities
WHERE ActivityDate >= '2010-12-16' AND ActivityDate < '2010-12-17'
GROUP BY UserID
Данные таблицы выглядят примерно так:
UserID ActivityDate t1 t2 t3 t4
1 2010-01-01 0 82 0 0
1 2010-01-02 100 1 12 0
2 2010-01-01 0 0 0 41
2 2010-01-02 0 0 0 1
3 2010-01-02 0 0 0 106
3 2010-01-03 2 5 0 4
Таблица очень большая (10M + строк), если я хочу получитьсписок идентификаторов пользователей, у которых были какие-либо точки активности для t1, t2 или t3 (но мы не хотим считать t4) в любой день.мой конечный результат будет включать в себя UserID 1 и 3.
, какой из следующих запросов лучше:
SELECT DISTINCT UserID
FROM summery_data
WHERE t1 > 0 OR t2 > 0 OR t3 > 0
против
SELECT UserID
FROM summery_data
GROUP BY UserID
HAVING SUM(t1) > 0 OR SUM(t2) > 0 OR SUM(t3) > 0
, чтобы понять, что будетбыстрее, у меня есть вопрос о том, что происходит за кулисами:
запрос DISTINCT, как база данных обеспечивает добавление только 1 идентификатора пользователя в набор результатов, проверяет ли онакаждый идентификатор пользователя, чтобы увидеть, если он уже существует в наборе?или поскольку таблица в любом случае кластеризована по UserID, просто сохраняйте переменную - при сканировании строк - последнего UserID, добавленного в набор результатов?
в запросе DISTINCT, После того как база данныхнайти одну строку, которая соответствует критериям для текущего идентификатора пользователя, останавливает ли он проверку предиката в предложении where, пока не достигнет следующего идентификатора пользователя?
в запросе GROUP BY при суммированиистолбец t1, когда база данных найдет запись о том, что столбец t1> 0, который будет соответствовать HAVING, прекратит ли суммировать другие строки t1 для текущего идентификатора пользователя (поскольку предикат> 0, что уже верно)?или, по крайней мере, он не суммирует другие столбцы (t2 и t3), поскольку в этом нет необходимости?или база данных сначала выполняет суммирование t1, t2 и t3 до , вычисляя предложение HAVING?
Примечание: я использую MySql в качестве сервера базы данных,Однако я хотел бы знать, если Sql Server или любые другие системы баз данных будут работать по-другому.
Любая помощь очень ценится.