Jawaban yang benar-benar gila, tetapi jika Anda memiliki semacam pengaturan sistem replikasi (untuk sistem dengan satu miliar baris, saya harap Anda melakukannya), Anda dapat menggunakan estimator kasar (seperti MAX(pk)
), bagi nilai itu dengan jumlah budak Anda punya, jalankan beberapa kueri secara paralel.
Untuk sebagian besar, Anda akan mempartisi kueri di seluruh budak berdasarkan kunci terbaik (atau kunci utama saya kira), sedemikian rupa (kita akan menggunakan 250000000 sebagai Baris / Budak kami):
-- 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
Tetapi Anda hanya perlu SQL. Benar-benar payah. Ok, jadi anggaplah Anda seorang sadomasochist. Pada master (atau slave terdekat) Anda kemungkinan besar perlu membuat tabel untuk ini:
CREATE TABLE counter_table (minpk integer, maxpk integer, cnt integer, slaveid integer)
Jadi, alih-alih hanya menjalankan seleksi di slave Anda, Anda harus melakukan insert, seperti ini:
INSERT INTO counter_table VALUES (I*25000000, (I+1)*250000000, (SELECT COUNT(pk) FROM ... ), @@SLAVE_ID)
Anda mungkin mengalami masalah dengan budak yang menulis ke meja di master. Anda mungkin perlu mendapatkan lebih banyak sadis- Maksudku, kreatif:
-- A table per slave!
INSERT INTO counter_table_slave_I VALUES (...)
Anda pada akhirnya harus memiliki budak yang ada di jalur terakhir yang dilalui oleh grafik replikasi, relatif terhadap budak pertama. Budak itu sekarang harus memiliki semua nilai counter lainnya, dan harus memiliki nilai sendiri. Tetapi pada saat Anda selesai, mungkin ada baris yang ditambahkan, jadi Anda harus memasukkan satu lagi untuk mengkompensasi pk max yang tercatat di counter_table Anda dan pk maks saat ini.
Pada titik itu, Anda harus melakukan fungsi agregat untuk mencari tahu apa total barisnya, tetapi itu lebih mudah karena Anda akan menjalankannya paling banyak pada "jumlah budak yang Anda miliki dan ubah" baris.
Jika Anda berada dalam situasi di mana Anda memiliki tabel terpisah di slave, Anda bisa UNION
mendapatkan semua baris yang Anda butuhkan.
SELECT SUM(cnt) FROM (
SELECT * FROM counter_table_slave_1
UNION
SELECT * FROM counter_table_slave_2
UNION
...
)
Atau Anda tahu, menjadi sedikit lebih tidak waras dan memigrasikan data Anda ke sistem pemrosesan terdistribusi, atau mungkin menggunakan solusi Data Warehousing (yang akan memberi Anda data yang luar biasa juga di masa depan).
Perhatikan, ini tergantung pada seberapa baik replikasi Anda diatur. Karena bottleneck utama kemungkinan besar adalah penyimpanan yang persisten, jika Anda memiliki penyimpanan yang kasar atau penyimpanan data yang terpisah dengan kebisingan tetangga yang tinggi, ini mungkin akan membuat Anda lebih lambat daripada hanya menunggu satu pun.SELECT COUNT(*) ...
Tetapi jika Anda memiliki replikasi yang baik, maka peningkatan kecepatan Anda harus langsung terkait dengan jumlah atau budak. Faktanya, jika hanya perlu 10 menit untuk menjalankan kueri penghitungan, dan Anda memiliki 8 budak, Anda akan memotong waktu Anda menjadi kurang dari beberapa menit. Mungkin satu jam untuk menyelesaikan detail dari solusi ini.
Tentu saja, Anda tidak akan pernah benar-benar mendapatkan jawaban yang luar biasa akurat karena penyelesaian terdistribusi ini memperkenalkan sedikit waktu di mana baris dapat dihapus dan dimasukkan, tetapi Anda dapat mencoba untuk mendapatkan kunci terdistribusi dari baris pada contoh yang sama dan mendapatkan penghitungan yang tepat dari baris dalam tabel untuk saat tertentu dalam waktu.
Sebenarnya, ini sepertinya tidak mungkin, karena pada dasarnya Anda terjebak dengan solusi SQL-only, dan saya tidak berpikir Anda menyediakan mekanisme untuk menjalankan kueri yang beling dan terkunci di banyak budak, secara instan. Mungkin jika Anda memiliki kendali atas file log replikasi ... yang berarti Anda benar-benar akan memutar budak untuk tujuan ini, yang tidak diragukan lagi lebih lambat daripada hanya menjalankan kueri hitungan pada satu mesin saja.
Jadi ada dua sen 2013 saya.