Буквально безумный ответ, но если у вас настроена какая-то система репликации (я надеюсь, что для системы с миллиардом строк), вы можете использовать приблизительную оценку (например, MAX(pk)
), разделить это значение на число подчиненных у вас есть, запустить несколько запросов параллельно.
По большей части вы будете распределять запросы между подчиненными на основе лучшего ключа (или, я полагаю, первичного ключа) таким образом (мы будем использовать 250000000 в качестве наших рядов / подчиненных):
-- First slave
SELECT COUNT(pk) FROM t WHERE pk < 250000000
-- Ith slave where 2 <= I <= N - 1
SELECT COUNT(pk) FROM t WHERE pk >= I*250000000 and pk < (I+1)*250000000
-- Last slave
SELECT COUNT(pk) FROM t WHERE pk > (N-1)*250000000
Но вам нужен только SQL. Что за бюст. Хорошо, так скажем, вы садомазохист. На главном (или ближайшем подчиненном) вам, скорее всего, нужно создать таблицу для этого:
CREATE TABLE counter_table (minpk integer, maxpk integer, cnt integer, slaveid integer)
Таким образом, вместо того, чтобы иметь только выборки, запущенные в ваших ведомых устройствах, вам нужно будет выполнить вставку, похожую на эту:
INSERT INTO counter_table VALUES (I*25000000, (I+1)*250000000, (SELECT COUNT(pk) FROM ... ), @@SLAVE_ID)
Вы можете столкнуться с проблемами при записи рабов в таблицу на ведущем устройстве. Вам может понадобиться еще больше садисов - я имею в виду, творческий подход:
-- A table per slave!
INSERT INTO counter_table_slave_I VALUES (...)
В конце концов у вас должен быть ведомый, который существует последним на пути, пройденном графом репликации, относительно первого ведомого. Это ведомое устройство должно теперь иметь все другие значения счетчика и иметь свои собственные значения. Но к тому времени, как вы закончите, вероятно, будут добавлены строки, так что вам нужно будет вставить еще одну, компенсирующую записанный max pk в вашей counter_table и текущий max pk.
На этом этапе вам нужно было бы выполнить агрегатную функцию, чтобы выяснить, каково общее количество строк, но это проще, так как вы будете запускать его не более чем на «число ведомых устройств, которые вы имеете и меняете».
Если вы находитесь в ситуации, когда у вас есть отдельные таблицы в ведомых устройствах, вы можете UNION
получить все необходимые вам строки.
SELECT SUM(cnt) FROM (
SELECT * FROM counter_table_slave_1
UNION
SELECT * FROM counter_table_slave_2
UNION
...
)
Или, знаете, будьте немного безумнее и перенесите свои данные в систему распределенной обработки, или, возможно, воспользуйтесь решением для хранилища данных (которое в будущем также даст вам потрясающий перебор данных).
Обратите внимание, это зависит от того, насколько хорошо настроена ваша репликация. Поскольку основным узким местом, скорее всего, будет постоянное хранилище, если у вас нечеткое хранилище или плохо сегрегированные хранилища данных с сильным шумом соседей, это, вероятно, будет работать медленнее, чем просто ожидание одногоSELECT COUNT(*) ...
Но если у вас хорошая репликация, то ваш прирост скорости должен быть напрямую связан с числом или рабами. Фактически, если для выполнения одного запроса подсчета требуется 10 минут, а у вас есть 8 подчиненных, вы бы сократили свое время до пары минут. Может быть, час, чтобы сгладить детали этого решения.
Конечно, вы никогда не получите действительно удивительно точного ответа, так как это распределенное решение вводит немного времени, когда строки могут быть удалены и вставлены, но вы можете попытаться получить распределенную блокировку строк в одном и том же экземпляре и получить точное количество строк в таблице на определенный момент времени.
На самом деле, это кажется невозможным, поскольку вы в основном застряли с решением только для SQL, и я не думаю, что у вас есть механизм, позволяющий мгновенно выполнять закрытый и заблокированный запрос для нескольких ведомых устройств. Возможно, если бы вы имели контроль над файлом журнала репликации ... это означает, что вы буквально раскручивали бы рабов для этой цели, что, без сомнения, медленнее, чем просто выполнение запроса подсчета на одной машине.
Так вот мои две копейки 2013 года.