Буквально божевільна відповідь, але якщо у вас створена якась система реплікації (для системи з мільярдом рядків, я сподіваюсь, що ви це зробите), ви можете використовувати приблизний оцінювач (як 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 (...)
Зрештою, у вас повинен бути підлеглий, який існує останнім у шляху, пройденому графіком реплікації, щодо першого підлеглого. Цей раб тепер повинен мати всі інші зустрічні значення, і він повинен мати свої власні значення. Але до того часу, коли ви закінчите, напевно додаються рядки, тому вам доведеться вставити ще один компенсуючи записаний макс 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 року.