Çok büyük bir tablodaki tam satır sayısını saymanın en hızlı yolu?


234

SELECT COUNT(*) FROM TABLE_NAMETablo çok satır ve sütun çok olduğunda yavaş olacağını bildiren makaleler rastladım .

Milyarlarca satır bile içerebilecek bir tablo var [yaklaşık 15 sütun vardır]. Bir tablonun satır sayısının EXACT sayısını almanın daha iyi bir yolu var mı ?

Lütfen cevabınızdan önce aşağıdakileri göz önünde bulundurun:

  • Ben bir veritabanı satıcısı bağımsız bir çözüm arıyorum. O kapsıyorsa Tamam olduğunu MySQL , Oracle , MS SQL Server . Ama gerçekten hiçbir veritabanı satıcısı bağımsız bir çözüm yoksa o zaman farklı veritabanı satıcıları için farklı çözümler için yerleşecektir.

  • Bunu yapmak için başka bir harici araç kullanamıyorum. Ben esas olarak SQL tabanlı bir çözüm arıyorum.

  • Veritabanı tasarımımı daha fazla normalleştiremiyorum. Zaten 3NF'de ve dahası etrafına çok sayıda kod yazıldı.


4
Ve sadece milyarlarca tane olduğunda neden tam anlık satırlara ihtiyaç duyulduğunu merak ediyorum ...
zerkms

2
Bu yapının veritabanı satıcımız tarafından optimize edildiğini umar mıyız?
KevinDTimm

5
@Swaranga, tablodaki satır sayısını tam olarak bilmesi gereken bu veritabanı bakım amacının ne olduğunu biraz daha açıklayabilir misiniz ? Hayal bile edemiyorum. Ve Kevin söylediği gibi, COUNT (*) ardından DBMS satıcı mutlaka (*) kullanmak için COUNT yeniden uygulamak (olmalı) olandan daha hızlı bir yolu olsaydı ...
Tony Andrews

3
Tabii ki sık sık tablo yazılıyorsa, tam sayınız yalnızca belirli bir zaman noktasında kesin olacaktır ve sorguya bir tablo kilidi koymadıkça, tabloya başka işlemler yazıyorsa bile doğru olmayabilir.
Steve Ford

2
Yuvarlama sayısını korumak için ekleme ve silme tetikleyicilerini kullanabilirsiniz?
paparazzo

Yanıtlar:


246

Basit cevap:

  • Veritabanı satıcısından bağımsız çözüm = standardı kullan = COUNT(*)
  • Orada yaklaşık SQL Server çözümleri ancak kapsam dışında = COUNT (*) kullanmayın

Notlar:

COUNT (1) = COUNT (*) = COUNT (PrimaryKey) ihtimale

Düzenle:

SQL Server örneği (1.4 milyar satır, 12 sütun)

SELECT COUNT(*) FROM MyBigtable WITH (NOLOCK)
-- NOLOCK here is for me only to let me test for this answer: no more, no less

1 koşu, 5:46 dakika, sayım = 1.401.659.700

--Note, sp_spaceused uses this DMV
SELECT
   Total_Rows= SUM(st.row_count)
FROM
   sys.dm_db_partition_stats st
WHERE
    object_name(object_id) = 'MyBigtable' AND (index_id < 2)

2 işlem, her ikisi de 1 saniyenin altında, sayı = 1.401.659.670

İkincisinin daha az satırı vardır = yanlış. Yazmaya bağlı olarak aynı veya daha fazla olurdu (silme işlemleri burada saatler dışında yapılır)


9
Hayır COUNT(*) = COUNT(key). Bu sadece yanlış. Herhangi bir NOT NULLkısıtlama yoksa - o zaman eşit olamazlar (sonuçlarda ve yürütme planında).
zerkms

14
@zerkmsby: COUNT (anahtar) için boş değerli olmaması gereken COUNT (birincil anahtar) demek istedim. Ben açıklamak edeceğiz
GBN

8
ile (NOLOCK) üretimde çalışmasına izin veren bir şey değildir ve yanlış bir sayıya yol açabilir. Bu ipucunu kullandığınızda, kilitleri önlediğinden emin olun, ancak bir üretim kutusundaki yan etkiler, bazı durumlarda satırları iki kez sayabileceğiniz veya diğer durumlarda satırları atlayabileceğinizdir. NOLOCK, "kirli okumalara" izin verdiği için yazılmamış bir tabloda kullanmak daha iyidir. Sonuçları tam olarak anlamadıkça insanlara bu ipucunu kullanmalarını önermeyin
Davos

4
@mishrsud Tek doğru sorgu SELECT COUNT (*), ancak yavaş. Tam ve yavaş ya da kaba ve hızlı olabilirsiniz. Yaptığınız şey, saymanız gereken amaç için neyin daha önemli olduğuna bağlı olacaktır. NO LOCK, herhangi bir nedenle işlem ortasında veya hareketli sayfa olan satırları içerebilir veya gerçekten hariç tutabilir.
Davos

5
@ gbn çok güzel bir çözüm, ne kullanıldığını söyleyebilir misiniz index_id < 2?
taahhüt

29

MySQL'de en hızlı yol:

SHOW TABLE STATUS;

İsterseniz tüm tablolarınızı satır sayısı (toplam) ile birlikte bol miktarda ekstra bilgi ile anında alacaksınız.


1
Akıllı yolu .. bu ile 1 sorguda birden çok tablo satır sayısı alabilirsiniz.
Deval Khandelwal

@ gbn gibi ~ milyar girişleri olan tabloları olan db üzerinde çalıştınız ve zamanı fark ettiniz mi?
KNU

veritabanındaki tüm tablolar için toplam satır sayısı nedir? Ve bunlar yaklaşıktır - tam satır sayısı değerlerini istiyorsanız?
Kreeverp

2
Bu hiç işe yaramıyor, örneğin INNODB'de, depolama motoru satır sayısını tahmin etmek için birkaç satır okuyor ve tahmin ediyor
Martijn Scheffer

10

Tabloda çok sayıda satır ve çok sayıda sütun olduğunda TABLE_NAME TARAFINDAN SELECT COUNT (*) ifadesinin yavaş olacağını belirten makalelerle karşılaştım.

Bu veritabanına bağlıdır. Bazıları hızlandırır, örneğin dizinde satırların canlı ya da ölü olup olmadığını takip ederek, bir dizin sadece satır sayısını çıkarmak için tarama sağlar. Diğerleri, tüm tabloyu ziyaret etmeyi ve canlı satırları tek tek saymayı gerektirmez ve sonuç olarak gerektirir. Her ikisi de büyük bir masa için yavaş olacaktır.

Örneğin, sorgu optimizasyon araçlarını, tablo istatistiklerini, vb. Kullanarak iyi bir tahmin elde edebileceğinizi unutmayın. Örneğin, PostgreSQL durumunda explain count(*) from yourtable, satırların çıktısını ayrıştırabilir ve satır sayısının makul derecede iyi bir tahminini alabilirsiniz. Bu da beni ikinci sorunuza getiriyor.

Milyarlarca satır bile içerebilecek bir tablo var [yaklaşık 15 sütun var]. Bir tablonun satır sayısının EXACT sayısını almanın daha iyi bir yolu var mı?

Ciddi anlamda? :-) Gerçekten milyarlarca satır içeren bir tablodan tam sayımı mı kastediyorsunuz ? Gerçekten emin misin? :-)

Eğer varsa gerçekten yapmak bunu yaparsanız, bir tetikleyicileri kullanarak toplam iz, ama zihin eşzamanlılık ve kilitlenme tutabilir.


Evet Denis, tam sayı gerekiyor. :(
Swaranga Sarma

5
Google yöneticilerinin patronunuzdan daha makul olması şanslı bir şeydir ... Tahmini bir sayıya bağlı kalmak yerine, sorgularınızın her biri için tam arama sonucu sayısını döndürürse ne kadar yavaş olacağını hayal edin.
Denis de Bernardy

En azından benimle empati kuruyorsun. Tek bir Oracle çözümüne ne dersiniz? Bu, sorunumu bir ölçüde azaltacaktır. Şu anda müşteri Oracle kullanıyor; yani yalnızca Oracle için bir geçici çözüm bulursam, [şimdilik] bunu yapacak. :)
Swaranga Sarma

6
"Evet Denis, tam sayım gerekiyor. :(" - iyi, sadece spekülasyon yapabilirim. Db bakım işlemi A tablosunda 42,123,876 satır olduğunu fark eder ve sonra B tablosunda 42,123,876 boş satır oluşturur ve sonra tabloyu döngüye alır A ve tablo B'deki satırları güncelleyin ...? Yoksa bundan daha çılgın mı? ;-)
Tony Andrews

1
İşlem 2, işlem 1 tamamlanmadan başlayamaz. "Sayım tablosu" güncellemesi olmadan, birçok güncelleme işlemi paralel olarak çalışabilir. "Sayımlar tablosu" ile, her işlem sayısını güncellemek için "bir bilet almak" gerekir. İşlemler bilet makinesinde sıraya girmeye başlar (zamanlayıcı, sayımlar tablosunda bir sonraki kilitin kimin olacağına karar verir).
Erwin Smout

10

Bir tablonun satır sayısının EXACT sayısını almanın daha iyi bir yolu var mı?

Sorunuzu basitçe cevaplamak için Hayır .

Bunu yapmak için DBMS'den bağımsız bir yola ihtiyacınız varsa, en hızlı yol her zaman olacaktır:

SELECT COUNT(*) FROM TableName

Bazı DBMS tedarikçilerinin yalnızca sistemleri için daha hızlı yolları olabilir. Bu seçeneklerin bazıları zaten diğer yanıtlarda yayınlanmıştır.

COUNT(*) DBMS (en azından herhangi bir PROD layık DB) tarafından optimize edilmelidir, bu yüzden optimizasyonlarını atlamaya çalışmayın.

Yan not:
Diğer sorgularınızın birçoğunun da tablo boyutunuz nedeniyle tamamlanması uzun zaman aldığından eminim. Performansla ilgili endişeleriniz muhtemelen şema tasarımınızı hızlı bir şekilde düşünerek ele alınmalıdır. Bunu değiştirmek için bir seçenek olmadığını söylediniz, ancak 10 + dakikalık sorguların da bir seçenek olmadığı ortaya çıkabilir. 3 NF Eğer hız gerekir ve kayıtlar yoksa bazen veri birkaç tablolarda bölünebilmesi zaman her zaman en iyi yaklaşım değildir zorunda birlikte saklanacak. Düşünmek için bir şey...


10

Bu komut dosyasını başka bir StackOverflow soru / cevap aldım:

SELECT SUM(p.rows) FROM sys.partitions AS p
  INNER JOIN sys.tables AS t
  ON p.[object_id] = t.[object_id]
  INNER JOIN sys.schemas AS s
  ON s.[schema_id] = t.[schema_id]
  WHERE t.name = N'YourTableNameHere'
  AND s.name = N'dbo'
  AND p.index_id IN (0,1);

Masamın 500 milyon kaydı var ve yukarıdaki getiriler 1ms'den az. O esnada,

SELECT COUNT(id) FROM MyTable

tam 39 dakika, 52 saniye sürüyor!

Aynı sayıda satır verirler (benim durumumda tam olarak 519326012).

Bunun her zaman böyle olup olmayacağını bilmiyorum.


Bu sorgu ile satır sayısını elde etmek için bir parametre ekleyebilir misiniz? Örnek: TABLO ADINDAN COUNT (1) tane seçin ColumnFiled = '1' Sorgunuzla birlikte?
VnDevil

Bu sayıdır - bu durumda satır (kayıt) sayısı "sayım" dır. "500 milyon kayıt" yaklaşık bir sayıydı ve "519326012" tam satır veya sayıydı. Satırlar = kayıtlar = sayım.
JakeJ

9

Bu sp_spaceused (Transact-SQL) deneyebilirsiniz

Geçerli veritabanında tablo, dizinlenmiş görünüm veya Hizmet Aracısı kuyruğu tarafından kullanılan satır sayısını, ayrılmış disk alanını ve disk alanını veya tüm veritabanı tarafından ayrılan ve kullanılan disk alanını görüntüler.


Sp_spaceused bana yaklaşık bir sayı vermeyecek mi?
Swaranga Sarma

1
Bilginize: Bu dahili olarak sys.dm_db_partition_stats kullanır
gbn

6

SQL Server sürümü 2005/2008 ise, bir tablodaki satır sayısını hesaplamak için DMV'leri kullanabilirsiniz:

-- Shows all user tables and row counts for the current database 
-- Remove is_ms_shipped = 0 check to include system objects 
-- i.index_id < 2 indicates clustered index (1) or hash table (0) 
SELECT o.name, 
 ddps.row_count 
FROM sys.indexes AS i 
 INNER JOIN sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID 
 INNER JOIN sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID 
 AND i.index_id = ddps.index_id 
WHERE i.index_id < 2 
 AND o.is_ms_shipped = 0 
ORDER BY o.NAME 

SQL Server 2000 veritabanı motoru için sysindexes çalışacaktır, ancak yakın gelecekte kaldırılabileceği için SQL Server'ın gelecekteki sürümlerinde kullanılmaması önerilir.

Alınan örnek kod: Tablo Satırı Hızlı ve Ağrısız Olarak Nasıl Alınır


Bu yaklaşık olarak tam değil : cevabımı görmek lütfen
gbn

Bunun doğru olmadığı bir örnek biliyor musunuz? AFAIK, güncellenmiş istatistiklere bağlı değildir.
Alireza Maddah


5

Yanıt veren diğerleri kadar hiçbir yere yakın değilim ama bir tablodan (aşırı alakalı değil) rastgele bir satır seçmek için kullandığım bir işlemle ilgili bir sorunum vardı ama referans tablomdaki satır sayısını bilmem gerekiyordu rastgele indeksi hesaplamak için. Geleneksel Count (*) veya Count (1) çalışmasını kullanarak, ancak zaman zaman sorgumu çalıştırmak için 2 saniye kadar alıyordu. Bunun yerine ('tbl_HighOrder' adlı masam için) kullanıyorum:

Declare @max int

Select @max = Row_Count
From sys.dm_db_partition_stats
Where Object_Name(Object_Id) = 'tbl_HighOrder'

Harika çalışıyor ve Management Studio'daki sorgu süreleri sıfır.


1
FWIW, kullandığınız HANGİ veritabanı satıcısından bahsetmelisiniz; İfadenin satıcıya bağlı olarak biraz farklı olacağını düşünüyorum.
ToolmakerSteve

5

Peki, 5 yıl geç ve yardımcı olup olmadığından emin değilim:

Hayır saymaya çalışıyordum. SQL Server Management Studio'yu kullanarak bir SQL Server tablosundaki satırların ve bazı taşma hatasına koştum, sonra aşağıdakileri kullandım:

seçmek COUNT_BIG [Dbname], (1) [Dbo] [FactSampleValue]..;

Sonuç :

24296650578 satırlar


5

Bu iyi bir makale buldum çabuk tablo için doğru satır sayısı almak: SQL Server-NASIL gelen martijnh1her senaryo için iyi bir özetleyelim veren.

Belirli bir koşula bağlı olarak bir sayı sağlamam gereken yerde genişletilmem gerekiyor ve bu kısmı anladığımda, bu cevabı daha da güncelleyeceğim.

Bu arada, makaleden detaylar:

Yöntem 1:

Sorgu:

SELECT COUNT(*) FROM Transactions 

Yorumlar:

Tam tablo taraması gerçekleştirir. Büyük masalarda yavaş.

Yöntem 2:

Sorgu:

SELECT CONVERT(bigint, rows) 
FROM sysindexes 
WHERE id = OBJECT_ID('Transactions') 
AND indid < 2 

Yorumlar:

Satır sayısını almanın hızlı yolu. İstatistiklere bağlıdır ve yanlıştır.

Büyük tablolar için önemli zaman alabilen COUNT_ROWS ile DBCC UPDATEUSAGE (Veritabanı) çalıştırın.

Yöntem 3:

Sorgu:

SELECT CAST(p.rows AS float) 
FROM sys.tables AS tbl 
INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and
idx.index_id < 2 
INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int) 
AND p.index_id=idx.index_id 
WHERE ((tbl.name=N'Transactions' 
AND SCHEMA_NAME(tbl.schema_id)='dbo')) 

Yorumlar:

SQL yönetim stüdyosunun satırları sayma şekli (tablo özelliklerine, depolamaya, satır sayısına bakın). Çok hızlı, ama yine de yaklaşık bir satır.

Yöntem 4:

Sorgu:

SELECT SUM (row_count) 
FROM sys.dm_db_partition_stats 
WHERE object_id=OBJECT_ID('Transactions')    
AND (index_id=0 or index_id=1); 

Yorumlar:

Hızlı (yöntem 2 kadar hızlı olmasa da) çalışma ve eşit derecede önemli, güvenilir.


Teşekkürler! Gerçekten yararlı bir ipucu. Yöntem 4 benim değil bu yüzden sistem tablolarını görüntüleme iznim yok. Ancak yöntem 3 yeterince iyidir.
Nicholas Humphrey

3

Her zaman en hızlı genel bir çözüm olduğunu düşünmüyorum: Bazı RDBMS / sürümleri SELECT COUNT(*)daha hızlı seçenekler kullanmak için özel bir optimizasyona sahipken, diğerleri sadece tablo taraması yapıyor. İkinci küme için dokümantasyon / destek sitelerine gitmeniz gerekir, bu da muhtemelen daha belirli bir sorgunun yazılması gerekir, genellikle bir dizine bir şekilde çarpar.

DÜZENLE:

Şemanıza ve veri dağıtımınıza bağlı olarak işe yarayabilecek bir düşünce şöyledir: artan bir değere, sayısal artan kimliğe, örneğin, hatta zaman damgasına veya tarihe gönderme yapan dizine alınmış bir sütununuz var mı? Ardından, silme işlemlerinin gerçekleşmediği varsayılarak, sayımı son bir değere (dünün tarihi, bazı son örnek noktalarında en yüksek kimlik değeri) kadar saklamak ve sayının ötesinde saymak ve dizinde çok hızlı bir şekilde çözülmesi mümkün olmalıdır . Elbette değerlere ve endekslere çok bağımlı, ancak herhangi bir DBMS'nin hemen hemen her sürümü için geçerlidir.


Çok iyi bir DBMS için bir dizin kullanmak umuyoruz SELECT COUNT(*). MySQL bile bunu yapıyor ...
sleske

silmelerin gerçekleşmediğini varsayarsak - cidden ?? ; p
ToolmakerSteve

3

Bu soruya geç kaldım, ama MySQL ile yapabileceğim şey (MySQL kullandığım gibi). Gözlemlerimi burada paylaşıyorum:

1) SELECT COUNT(*) AS TOTAL_ROWS FROM <TABLE_NAME>

Sonuç
Satır Sayısı: 508534
Konsol çıktısı: Etkilenen satırlar: 0 Bulunan satırlar: 1 Uyarılar: 0 1 sorgulama süresi: 0.125 sn.
Çok sayıda satır içeren bir tablo için biraz zaman alır, ancak satır sayısı çok doğrudur.

2) SHOW TABLE STATUS or SHOW TABLE STATUS WHERE NAME="<TABLE_NAME>"

Sonuç
Satır sayısı: 511235
Konsol çıktısı: Etkilenen satırlar: 0 Bulunan satırlar: 1 Uyarılar: 0 1 sorgu süresi: 0.250 sn Özet: Satır sayısı tam değil.

3) SELECT * FROM information_schema.tables WHERE table_schema = DATABASE();

Sonuç
Satır sayısı: 507806
Konsol çıkışı: Etkilenen satırlar: 0 Bulunan satırlar: 48 Uyarılar: 0 1 sorgulama süresi: 1.701 sn.
Satır sayısı tam değil.

Ben bir MySQL veya veritabanı uzmanı değilim, ama çok büyük tablolar için seçenek 2 veya 3 kullanabilirsiniz ve kaç satır mevcut 'adil bir fikir' alabilirsiniz bulduk.

Kullanıcı arayüzünde bazı istatistikleri görüntülemek için bu satır sayılarını almam gerekiyordu. Yukarıdaki sorgularla, toplam satırların 500.000'den fazla olduğunu biliyordum, bu yüzden tam satır sayısını göstermeden "500.000'den fazla satır" gibi istatistikler gösterdim.

Belki OP'nin sorusunu gerçekten cevaplamadım, ancak bu tür istatistiklerin gerekli olduğu bir durumda yaptığım şeyi paylaşıyorum. Benim durumumda, yaklaşık satırları göstermek kabul edilebilir ve böylece yukarıdaki benim için çalıştı.


2

Tam olarak DBMS-agnostik bir çözüm değil, ama en azından müşteri kodunuz farkı görmeyecek ...

Yalnızca bir satır ve bir tamsayı alanı N 1 ile başka bir tablo T oluşturun ve sadece yürüten INSERT TRIGGER oluşturun:

UPDATE T SET N = N + 1

Ayrıca aşağıdakileri çalıştıran bir DELETE TRIGGER oluşturun:

UPDATE T SET N = N - 1

Tuzuna değer bir DBMS , 2'nin üzerindeki işlemlerin atomisitesini garanti eder ve N, her zaman doğru sayıda satır içerecektir, bu da daha sonra basitçe elde etmek için süper hızlıdır:

SELECT N FROM T

Tetikleyiciler DBMS'ye özgü olsa da, T'den seçim yapmak istemez ve istemci kodunuzun desteklenen her DBMS için değişmesi gerekmez.

Ancak, tablo INSERT veya DELETE-yoğunsa, özellikle INSERT / DELETE'den hemen sonra COMMIT yapmadıysanız, bu durum bazı ölçeklenebilirlik sorunlarına neden olabilir.


1 Bu isimler sadece yer tutuculardır - üretimde daha anlamlı bir şey kullanın.

2 Ie N, hem okuma hem de yazma tek bir SQL deyiminde yapıldığı sürece, okuma ve yazma arasındaki N ile aynı anda yapılan bir işlemle değiştirilemez.


2

Kelimenin tam anlamıyla deli bir cevap, ancak bir çeşit çoğaltma sistemi kurduysanız (milyar satırlık bir sistem için, umarım yaparsınız), kaba bir tahminci (örneğin MAX(pk)) kullanabilirsiniz, bu değeri köle sayısına bölebilirsiniz birkaç sorguyu paralel olarak çalıştırın.

Çoğunlukla, sorguları en iyi anahtara (veya tahmin ettiğim birincil anahtara) dayalı olarak slave'ler arasında bölümlendirirsiniz (Satırlarımız / Kölelerimiz olarak 250000000 kullanacağız):

-- 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

Ancak yalnızca SQL'e ihtiyacınız var. Ne baskın. Tamam, diyelim ki sen bir sadomasochistsin. Master'da (veya en yakın köle), büyük olasılıkla bunun için bir tablo oluşturmanız gerekir:

CREATE TABLE counter_table (minpk integer, maxpk integer, cnt integer, slaveid integer)

Bu yüzden, sadece seçimlerin kölelerinizde çalışması yerine, buna benzer bir ek yapmanız gerekir:

INSERT INTO counter_table VALUES (I*25000000, (I+1)*250000000, (SELECT COUNT(pk) FROM ... ), @@SLAVE_ID)

Efendide bir tabloya yazılan kölelerle ilgili sorunlarla karşılaşabilirsiniz. Daha da üzülmeniz gerekebilir - yani yaratıcı:

-- A table per slave!
INSERT INTO counter_table_slave_I VALUES (...)

Sonunda, ilk slave'e göre çoğaltma grafiğinin kat ettiği yolda en son var olan bir köle olmalıdır. Bu köle artık diğer tüm sayaç değerlerine sahip olmalı ve kendi değerlerine sahip olmalıdır. Ancak bitirdiğinizde, muhtemelen satırlar eklenir, bu nedenle counter_table cihazınıza ve geçerli max pk'nize kaydedilen maksimum pk'yi telafi eden başka bir satır eklemeniz gerekir.

Bu noktada, toplam satırların ne olduğunu bulmak için bir toplama işlevi yapmanız gerekir, ancak bunu en fazla "sahip olduğunuz köle sayısı ve değiştirme" satırlarında çalıştırdığınız için daha kolaydır.

Kölelerde ayrı tabloların olduğu durumdaysanız, UNIONihtiyacınız olan tüm satırları alabilirsiniz.

SELECT SUM(cnt) FROM (
    SELECT * FROM counter_table_slave_1
      UNION
    SELECT * FROM counter_table_slave_2
      UNION
    ...
  )

Ya da, biraz daha az deli olun ve verilerinizi dağıtılmış bir işleme sistemine taşıyın ya da belki de Veri Depolama çözümünü kullanın (bu da gelecekte müthiş veri çöküşü sağlayacaktır).

Unutmayın, bu, çoğaltmanızın ne kadar iyi ayarlandığına bağlıdır. Birincil darboğaz büyük olasılıkla kalıcı depolama olacağından, eğer kirli depolama alanınız veya ağır komşu gürültüsü olan zayıf ayrılmış veri depolarınız varsa, bu muhtemelen tek bir beklemekten daha yavaş çalışacaktırSELECT COUNT(*) ...

Ancak iyi bir çoğaltmanız varsa, hız kazançlarınız doğrudan sayı veya kölelerle ilişkili olmalıdır. Aslında, sayma sorgusunu tek başına çalıştırmak 10 dakika alırsa ve 8 köle varsa, zamanınızı birkaç dakikadan daha kısa bir sürede kesersiniz. Bu çözümün ayrıntılarını ütülemek için belki bir saat.

Tabii ki, asla gerçekten inanılmaz doğru bir cevap alamazsınız çünkü bu dağıtılmış çözme, satırların silinebileceği ve eklenebileceği biraz zaman tanıtır, ancak aynı örnekte dağıtılmış bir satır kilidi elde etmeye ve kesin bir sayı elde etmeye çalışabilirsiniz. tablodaki satırların belirli bir an için

Aslında, bu sadece imkansız görünüyor, çünkü temelde sadece SQL çözümüyle sıkışıp kaldınız ve anında birden fazla köle arasında parçalanmış ve kilitli bir sorgu çalıştırmak için bir mekanizma sağlandığınızı düşünmüyorum. Belki çoğaltma günlük dosyasını denetlemiş olsaydınız ... bu da tam anlamıyla köleleri bu amaçla döndürdüğünüz anlamına gelir, bu da hiç kuşkusuz tek bir makinede sayım sorgusunu çalıştırmaktan daha yavaştır.

Benim iki 2013 peni var.


2

Eğer ekleme tetikleyicisi kullanımına çok pahalı, ama bir silme tetiği tanınan olabilir ve otomatik artışlı varid , o zaman bir kez tüm tabloyu sayma ve olarak sayar hatırlamak sonra last-countve last-counted-id,

Daha sonra her gün sadece saymak gerekir id> last-counted-id, bu ekleyebilir last-countve yeni saklamak last-counted-id.

Silme kaydı <= son sayılan kimlik kimliği silindiğinde silme tetikleyicisi son sayıyı azaltır.


.. üzgünüm kullanılacak SQL göstermek için zaman yok (benim SQL paslı). Birisi SQL eklemek için cevabımı düzenlemek isterse, bu harika olurdu!
ToolmakerSteve

1

Satırların asla silinmediği otomatik artan birincil anahtar sütununa sahip tipik bir tablo yapınız varsa, aşağıdakiler kayıt sayısını belirlemenin en hızlı yolu olacaktır ve çoğu ANSI uyumlu veritabanında benzer şekilde çalışmalıdır:

SELECT TOP(1) <primarykeyfield> FROM <table> ORDER BY <primarykeyfield> DESC;

Kayıt sayısı da dahil olmak üzere veri için ikinci saniye yanıt süreleri gerektiren milyarlarca satır içeren MS SQL tabloları ile çalışıyorum. Benzer bir SELECT COUNT (*) işleminin karşılaştırılması birkaç dakika sürebilir.


1
Tamamen doğru değil - bir INSERTişlem geri alınırsa ne olur ? Bu birincil anahtar değeri olmayacaktır, bu nedenle gerçek kayıt sayısı maksimum değerden bir daha az olacaktır.
Sir Crispalot

Sırayla boşluklar olabilir. Genellikle geri dönüşlerin bir sonucudur.
Osa E

Aslında, count(*)bir veritabanı satıcısı yeterince optimize edilmemişse , bu cevabın önemli ölçüde daha hızlı olabileceği bir değişiklik vardır count(*): Her gün son otomatik endeksi ve karşılık gelen sayıyı takip edin, ardından bunun ötesinde bir kayıt sayısı isteyin. Ayrıca deletesilme işlemine bir önceki toplamı azaltan bir tetikleyici eklerse, silinen kayıt kimliği <= son otomatik dizin ise s ile başa çıkabilir .
ToolmakerSteve

1

Sql sunucusu için bunu deneyin

SELECT T.name, 
       I.rows AS [ROWCOUNT] 
FROM   sys.tables AS T 
       INNER JOIN sys.sysindexes AS I 
               ON T.object_id = I.id AND I.indid < 2 
WHERE T.name = 'Your_Table_Name'
ORDER  BY I.rows DESC 

0

sysindexes'den satırlar seçin; burada id = Object_ID ('TableName') ve indid <2


0

Bazı sütunlara bir dizin koyun. Bu, iyileştiricinin tablonun tam taraması yerine dizin bloklarının tam bir taramasını gerçekleştirmesine izin vermelidir. Bu, ES maliyetlerinizi düşürecektir. Önce ve sonra yürütme planına bakın. Ardından duvar saati süresini her iki şekilde ölçün.


Bir tablonun herhangi bir sütunda dizini olmayan milyarlarca satır varsa, orijinal soruda ifade edilen ihtiyacın çok ötesinde yaygın performans sorunları olacaktır .. ancak bundan bahsettiğiniz iyi (hiçbir şey varsaymayın!) :)
ToolmakerSteve

0

Oracle kullanıyorsanız buna ne dersiniz (tablo istatistiklerinin güncellendiği varsayılarak):

select <TABLE_NAME>, num_rows, last_analyzed from user_tables

last_analyzed, istatistiklerin en son ne zaman toplandığını gösterir.


0

PostgreSQL ile:

SELECT reltuples AS approximate_row_count FROM pg_class WHERE relname = 'table_name'

-1

SQL Server 2016'da, sadece tablo özelliklerini kontrol edebilir ve sonra 'Depolama' sekmesini seçebilirim - bu bana satır sayısı, tablo tarafından kullanılan disk alanı, kullanılan dizin alanı vb.


Bir şey arıyordu database vendor independent solution. Ayrıca bu bir GUI gerektirir ve otomatikleştirilemez. Ayrıca COUNT (*) olarak daha hızlı değil
Frieder

-3

Belki biraz geç ama bu MSSQL için başkalarına yardımcı olabilir

; TABLE_NAME ÜZERİNDEN [RowNumber] AS OLARAK (ROW_NUMBER () ÜZERİNDE SELECT ROW_NUMBER () SEÇIN ile RecordCount SEÇ MAX (RowNumber)


ÇOK şanslı olmadıkça ve optimize edici bunu bir COUNT () değerine optimize etmeyi başarmadığı sürece, bu COUNT () 'dan önemli ölçüde WORSE' dir - neden rastgele bir sütunda SORT'a sor?
dsz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.