MySQL - Satırları saymak için count (*) ve information_schema.tables arasındaki fark


16

Masamda birkaç milyon satır içeren satır sayısını saymanın hızlı bir yolunu istiyorum. Sorunumu çözecek gibi görünüyordu Stack Overflow, " MySQL: satır sayısını saymanın en hızlı yolu " yazısını buldum. Bayuah bu cevabı verdi:

SELECT
    table_rows "Rows Count"
FROM
    information_schema.tables
WHERE
    table_name="Table_Name"
AND
    table_schema="Database_Name";

Bunu sevdim çünkü tarama yerine bir arama gibi görünüyor, bu yüzden hızlı olmalı, ama test etmeye karar verdim

SELECT COUNT(*) FROM table 

performans farkının ne kadar olduğunu görmek için.

Maalesef aşağıda gösterildiği gibi farklı cevaplar alıyorum :

resim açıklamasını buraya girin

Soru

Cevaplar neden yaklaşık 2 milyon satırdan farklı? Tam bir tablo tarama gerçekleştiren sorgu daha doğru sayı olduğunu tahmin ediyorum, ama bu yavaş sorguyu çalıştırmak zorunda kalmadan doğru numarayı alabilirsiniz bir yolu var mı?


Koştum ANALYZE TABLE data_302, 0.05 saniyede tamamlandı. Sorguyu yeniden çalıştırdığımda, artık 34384599 satırın çok daha yakın bir sonucunu alıyorum, ancak yine de select count(*)34906061 satırlarıyla aynı sayı değil . Analiz tablosu hemen geri dönüyor ve arka planda işliyor mu? Bu bir test veritabanı ve şu anda yazılmıyor bahsetmeye değer hissediyorum.

Kimse sadece bir masanın ne kadar büyük olduğunu söyleyen bir durumda olup olmadığını umursamayacak, ancak veritabanını sorgulamak için "eşit boyutta" eşzamansız sorgular oluşturmak için bu rakamı kullanacak bir kod koduna satır sayısını iletmek istedim paralel olarak, Alexander Rubin'in paralel sorgu yürütmesiyle yavaş sorgu performansını artırmada gösterilen yönteme benzer . Olduğu gibi, ben sadece en yüksek kimliği almak SELECT id from table_name order by id DESC limit 1ve benim tablolar çok parçalanmış umuyoruz.

Yanıtlar:


23

Bir tablodaki satırları "saymanın" çeşitli yolları vardır. En iyi olan şey gereksinimlere bağlıdır (sayımın doğruluğu, ne sıklıkta gerçekleştirildiği, tüm tablonun sayısına mı yoksa değişken whereve group byyan tümceler ile mi, vb.)

  • a) normal yol. Sadece say .

    select count(*) as table_rows from table_name ; 

    Doğruluk : Sorgu çalıştırıldığında% 100 doğru sayım.
    Verimlilik : Büyük masalar için iyi değildir. (MyISAM tabloları için olağanüstü hızlıdır, ancak InnoDB'den çok dezavantajı olduğu için bu günlerde hiç kimse MyISAM kullanmamaktadır. " Olağanüstü hızlı" yalnızca tüm MyISAM tablosunun satırlarını sayarken de geçerlidir - sorgunun bir WHEREkoşulu varsa, hala tabloyu veya bir dizini taramak zorundadır.)
    InnoDB tabloları için, tablonun büyüklüğüne bağlıdır, çünkü motor doğru sayımı elde etmek için tüm tabloyu veya tüm indeksi taramak zorundadır. Masa büyüdükçe yavaşlar.

  • b)SQL_CALC_FOUND_ROWS ve kullanmak FOUND_ROWS(). Ayrıca, az sayıda satır da istiyorsak, önceki yol yerine kullanılabilir (değiştirerek LIMIT). Ben sayfalama için kullanılan gördüm (bazı satırlar almak ve aynı zamanda kaç int toplam olduğunu bilmek ve pgeg sayısını hesaplamak için).

    select sql_calc_found_rows * from table_name limit 0 ; 
    select found_rows() as table_rows ;

    Doğruluk : öncekiyle aynı.
    Verimlilik : öncekiyle aynı.

  • c) kullanılarak information_schemabağlanmış bir soru olarak, tablolar:

    select  table_rows
    from    information_schema.tables
    where   table_schema = 'database_name'
      and   table_name = 'table_name' ;

    Doğruluk : Sadece bir yaklaşım. Tablo sık sık eklenen ve silinen hedef ise, sonuç gerçek sayımdan çok uzak olabilir. Bu ANALYZE TABLEdaha sık çalışarak geliştirilebilir .
    Verimlilik : Çok iyi, masaya hiç dokunmuyor.

  • d) sayımı veritabanında saklamak (başka bir "sayaç" tablosunda ) ve tablonun bir ekleme, silme veya kısaltması olduğunda bu değeri güncelleyin (bu, tetikleyicilerle veya ekleme ve silme prosedürlerini değiştirerek elde edilebilir) .
    Bu elbette her ek parçaya ek bir yük koyar ve siler, ancak doğru bir sayı sağlayacaktır.

    Doğruluk :% 100 doğru sayım.
    Verimlilik : Çok iyi, başka bir tablodan sadece bir satır okuması gerekiyor.
    Ancak veritabanına ek yük getirir.

  • e) sayımı uygulama katmanında saklamak ( önbelleğe almak ) ve 1. yöntemi (veya önceki yöntemlerin bir kombinasyonunu) kullanarak. Örnek: tam sayım sorgusunu 10 dakikada bir çalıştırın. İki sayım arasındaki ortalama süre içinde önbelleğe alınan değeri kullanın.

    Doğruluk : yaklaşıklık, ancak normal koşullarda çok kötü değil (binlerce satır eklendiğinde veya silinmediği sürece).
    Verimlilik : Çok iyi, değer her zaman mevcuttur.


1

İçin INNODBistediğiniz information_schema.INNODB_SYS_TABLESTATS.NUM_ROWSyerine, doğru tablo satır sayısı verileri için information_schema.TABLES.TABLE_ROWS.

Burada daha fazla ayrıntı yayınladım: /programming/33383877/why-does-information-schema-tables-give-such-an-unstable-answer-for-number-of-ro/49184843#49184843


1
Yanlış bilgi ... "InnoDB'nin için, doğru tablo satır için information_schema.INNODB_SYS_TABLESTATS.NUM_ROWS istiyorum:" manuel açıkça söylüyor tahmin üzerine NUM_ROWScolum
Raymond Nijland
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.