Abrufen der Datensatzanzahl für alle Tabellen in der MySQL-Datenbank

347

Gibt es eine Möglichkeit, die Anzahl der Zeilen in allen Tabellen in einer MySQL-Datenbank zu ermitteln, ohne SELECT count()für jede Tabelle eine auszuführen ?

Kennzeichen
quelle
1
Erweiterte Antwort, die auch für InnoDB korrekt ist
gwideman
1
SELECT count (table_name) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'YOUR_DB' gibt die Anzahl der Tabellen in Ihrer Datenbank an
shasi kanth

Antworten:

416
SELECT SUM(TABLE_ROWS) 
     FROM INFORMATION_SCHEMA.TABLES 
     WHERE TABLE_SCHEMA = '{your_db}';

Hinweis aus den Dokumenten: Bei InnoDB-Tabellen ist die Zeilenanzahl nur eine grobe Schätzung, die bei der SQL-Optimierung verwendet wird. Sie müssen COUNT (*) für genaue Zählungen verwenden (was teurer ist).

Hates_
quelle
266
oder, wenn Sie für jede Tabelle möchten: SELECT table_name, TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{your_db}';
TheSoftwareJedi
5
Gibt es eine andere Möglichkeit, table_row und table_name abzurufen? Weil ich ein genaues Ergebnis will, keine grobe Schätzung. Vielen Dank.
Krunal Shah
3
@krunalshah, Dies ist eine der Einschränkungen von InnoDB. Weitere Informationen finden Sie unter dev.mysql.com/doc/refman/5.0/de/innodb-restrictions.html , Abschnitt Einschränkungen für InnoDB-Tabellen. Sie können immer einen SELECT COUNT (*) FROM t verwenden, der jedoch viel langsamer ist
Markierung
2
Jaitsu, nein ist es nicht. count (*) (oder realistischer count (id)) ist das, was MySQL verwendet, um seine Zeilen zu zählen, nicht wahr? Auf jeden Fall habe ich es gerade getestet und eine größere Nummer für den Aufruf von count () bekommen, was auch immer das wert ist.
Codygman
2
SELECT TABLE_NAME, SUM (TABLE_ROWS) N FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{your_db}' Gruppe nach TABLE_NAME;
PiyusG
175

Sie können wahrscheinlich etwas mit Tabellen Tabelle zusammenstellen . Ich habe es noch nie gemacht, aber es sieht so aus, als hätte es eine Spalte für TABLE_ROWS und eine für TABLE NAME .

Um Zeilen pro Tabelle abzurufen, können Sie eine Abfrage wie die folgende verwenden:

SELECT table_name, table_rows
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '**YOUR SCHEMA**';
gpojd
quelle
4
Gibt es eine andere Möglichkeit, table_row und table_name abzurufen? Weil ich ein genaues Ergebnis will, keine grobe Schätzung. Vielen Dank.
Krunal Shah
1
Wie Kuranl erwähnte, gibt dies nur eine Schätzung zurück und wird wahrscheinlich unterschiedliche Ergebnisse liefern, wenn es ein paar Mal ausgeführt wird
Kris
Tabellen mit mindestens ~ 250 Datensätzen scheinen bei jeder Ausführung dieser Abfrage eine andere Anzahl von Zeilen zu melden.
Arthur
Hoppla ... wünschte, ich hätte das Wort "Geschätzt" schon vorher gesehen ... wie gestern! Sollte die Antwort nicht abgelehnt werden? Da OP nicht nach "geschätzt" gefragt hat und es albern erscheint zu denken, dass er vielleicht eine Schätzung will. "Schätzung" Könnten Kastanienbraune wie ich davor bewahren, die "Schätzung" zu verpassen?
Kreeverp
111

Wie @Venkatramanan und andere fand ich INFORMATION_SCHEMA.TABLES unzuverlässig (unter Verwendung von InnoDB, MySQL 5.1.44) und gab jedes Mal, wenn ich es auch in stillgelegten Tabellen ausführe, unterschiedliche Zeilenzahlen an. Hier ist eine relativ hackige (aber flexible / anpassbare) Möglichkeit, eine große SQL-Anweisung zu generieren, die Sie in eine neue Abfrage einfügen können, ohne Ruby-Edelsteine ​​und andere Dinge zu installieren.

SELECT CONCAT(
    'SELECT "', 
    table_name, 
    '" AS table_name, COUNT(*) AS exact_row_count FROM `', 
    table_schema,
    '`.`',
    table_name, 
    '` UNION '
) 
FROM INFORMATION_SCHEMA.TABLES 
WHERE table_schema = '**my_schema**';

Es erzeugt eine Ausgabe wie folgt:

SELECT "func" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.func UNION                         
SELECT "general_log" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.general_log UNION           
SELECT "help_category" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.help_category UNION       
SELECT "help_keyword" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.help_keyword UNION         
SELECT "help_relation" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.help_relation UNION       
SELECT "help_topic" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.help_topic UNION             
SELECT "host" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.host UNION                         
SELECT "ndb_binlog_index" AS table_name, COUNT(*) AS exact_row_count FROM my_schema.ndb_binlog_index UNION 

Kopieren und Einfügen mit Ausnahme der letzten UNION, um eine schöne Ausgabe zu erhalten wie:

+------------------+-----------------+
| table_name       | exact_row_count |
+------------------+-----------------+
| func             |               0 |
| general_log      |               0 |
| help_category    |              37 |
| help_keyword     |             450 |
| help_relation    |             990 |
| help_topic       |             504 |
| host             |               0 |
| ndb_binlog_index |               0 |
+------------------+-----------------+
8 rows in set (0.01 sec)
Nathan
quelle
2
Danke, ich hatte gehofft, ich müsste keine Plugins / Gems installieren, um genaue Zählungen zu erhalten.
Bradvido
Die Ausführung dauert bei einer großen Anzahl von Tabellen in der Datenbank zu lange.
Ollamh
1
Fügen Sie am Ende der generierten Abfrage nach dem Entfernen der letzten UNION "select * from (" am Anfang und ") als Ausgabereihenfolge von sure_row_count desc" hinzu, um die Reihenfolge nach Tabellenanzahl desc zu erhalten
Raghavendra
So schließen Sie Ansichten aus: WHERE table_schema = ' my_schema ' und TABLE_TYPE LIKE '% TABLE%'
Watson
38

Ich renne einfach:

show table status;

Auf diese Weise erhalten Sie die Zeilenanzahl für JEDE Tabelle sowie eine Reihe weiterer Informationen. Ich habe die oben ausgewählte Antwort verwendet, aber das ist viel einfacher.

Ich bin nicht sicher, ob dies mit allen Versionen funktioniert, aber ich verwende 5.5 mit InnoDB-Engine.

djburdick
quelle
5
Wenn Sie InnoDB verwenden, weist dieser Ansatz leider dieselben Ungenauigkeiten auf wie die anderen oben beschriebenen Methoden. Zum Beispiel habe ich eine InnoDB-Tabelle mit ungefähr 65.000 Zeilen, aber diese Methoden hier berichten, dass sie zwischen 350.000 und über 780.000 hat.
PeterToTheThird
Für eine Datenbank mit wenigen Zeilen ist sie ziemlich genau (oder genau genug für meine Anforderungen). Es gab mir 1086 Zeilen für eine Tabelle, die COUNT (*) 904 Zeilen meldete.
Magne
Mit Abstand beste Antwort. Ich benutze InnoDB, aber ich brauche nur einen schnellen Befehl, um die Größenordnung zu kennen.
Nemo
Im Ernst, ich wünschte, dies würde akzeptiert. Ich benutze InnoDB nicht und gebe mir eine genaue Antwort.
Kolob Canyon
1
Die Zeilennummer ist nicht korrekt, aber "Auto_increment" kann Ihnen eine genaue Nummer geben, wenn Sie keine Zeilen aus solchen Tabellen gelöscht haben.
Peter T.
13
 SELECT TABLE_NAME,SUM(TABLE_ROWS) 
 FROM INFORMATION_SCHEMA.TABLES 
 WHERE TABLE_SCHEMA = 'your_db' 
 GROUP BY TABLE_NAME;

Das ist alles was du brauchst.

Gustavo Castro
quelle
1
erzeugt geschätzte Tabellenzeilen - vergleiche mit "mysql_num_rows ($ tableresult)"
Kreeverp
1
Das ist eigentlich die beste Antwort! Auch die einfachere Ausführung von mysql> SELECT TABLE_NAME,SUM(TABLE_ROWS) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ngramsdb' GROUP BY TABLE_NAME;
MySQL Cli
11

Diese gespeicherte Prozedur listet Tabellen auf, zählt Datensätze und erzeugt am Ende eine Gesamtzahl von Datensätzen.

So führen Sie es nach dem Hinzufügen dieses Verfahrens aus:

CALL `COUNT_ALL_RECORDS_BY_TABLE` ();

- -

Der Ablauf:

DELIMITER $$

CREATE DEFINER=`root`@`127.0.0.1` PROCEDURE `COUNT_ALL_RECORDS_BY_TABLE`()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE TNAME CHAR(255);

DECLARE table_names CURSOR for 
    SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE();

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

OPEN table_names;   

DROP TABLE IF EXISTS TCOUNTS;
CREATE TEMPORARY TABLE TCOUNTS 
  (
    TABLE_NAME CHAR(255),
    RECORD_COUNT INT
  ) ENGINE = MEMORY; 


WHILE done = 0 DO

  FETCH NEXT FROM table_names INTO TNAME;

   IF done = 0 THEN
    SET @SQL_TXT = CONCAT("INSERT INTO TCOUNTS(SELECT '" , TNAME  , "' AS TABLE_NAME, COUNT(*) AS RECORD_COUNT FROM ", TNAME, ")");

    PREPARE stmt_name FROM @SQL_TXT;
    EXECUTE stmt_name;
    DEALLOCATE PREPARE stmt_name;  
  END IF;

END WHILE;

CLOSE table_names;

SELECT * FROM TCOUNTS;

SELECT SUM(RECORD_COUNT) AS TOTAL_DATABASE_RECORD_CT FROM TCOUNTS;

END
Jake Drew
quelle
8

Einfacher Weg:

SELECT
  TABLE_NAME, SUM(TABLE_ROWS)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '{Your_DB}'
GROUP BY TABLE_NAME;

Ergebnisbeispiel:

+----------------+-----------------+
| TABLE_NAME     | SUM(TABLE_ROWS) |
+----------------+-----------------+
| calls          |            7533 |
| courses        |             179 |
| course_modules |             298 |
| departments    |              58 |
| faculties      |             236 |
| modules        |             169 |
| searches       |           25423 |
| sections       |             532 |
| universities   |              57 |
| users          |           10293 |
+----------------+-----------------+
Eduardo Cuomo
quelle
4

Es gibt eine Art Hack / Workaround für dieses Schätzungsproblem.

Auto_Increment - Aus irgendeinem Grund wird dadurch eine viel genauere Zeilenanzahl für Ihre Datenbank zurückgegeben, wenn für Tabellen ein automatisches Inkrement eingerichtet wurde.

Dies wurde festgestellt, als untersucht wurde, warum die Tabelleninformationen nicht mit den tatsächlichen Daten übereinstimmen.

SELECT
table_schema 'Database',
SUM(data_length + index_length) AS 'DBSize',
SUM(TABLE_ROWS) AS DBRows,
SUM(AUTO_INCREMENT) AS DBAutoIncCount
FROM information_schema.tables
GROUP BY table_schema;


+--------------------+-----------+---------+----------------+
| Database           | DBSize    | DBRows  | DBAutoIncCount |
+--------------------+-----------+---------+----------------+
| Core               |  35241984 |   76057 |           8341 |
| information_schema |    163840 |    NULL |           NULL |
| jspServ            |     49152 |      11 |            856 |
| mysql              |   7069265 |   30023 |              1 |
| net_snmp           |  47415296 |   95123 |            324 |
| performance_schema |         0 | 1395326 |           NULL |
| sys                |     16384 |       6 |           NULL |
| WebCal             |    655360 |    2809 |           NULL |
| WxObs              | 494256128 |  530533 |        3066752 |
+--------------------+-----------+---------+----------------+
9 rows in set (0.40 sec)

Sie können dann problemlos PHP oder was auch immer verwenden, um das Maximum der 2 Datenspalten zurückzugeben und die "beste Schätzung" für die Zeilenanzahl zu erhalten.

dh

SELECT
table_schema 'Database',
SUM(data_length + index_length) AS 'DBSize',
GREATEST(SUM(TABLE_ROWS), SUM(AUTO_INCREMENT)) AS DBRows
FROM information_schema.tables
GROUP BY table_schema;

Bei der automatischen Inkrementierung sind immer +1 * (Tabellenanzahl) Zeilen deaktiviert, aber selbst bei 4.000 Tabellen und 3 Millionen Zeilen ist die Genauigkeit 99,9%. Viel besser als die geschätzten Zeilen.

Das Schöne daran ist, dass die in performance_schema zurückgegebenen Zeilenzahlen auch für Sie gelöscht werden, da das Größte bei Nullen nicht funktioniert. Dies kann jedoch ein Problem sein, wenn Sie keine Tabellen mit automatischer Inkrementierung haben.

user3260912
quelle
3

Sie können dies versuchen. Es funktioniert gut für mich.

SELECT IFNULL(table_schema,'Total') "Database",TableCount 
FROM (SELECT COUNT(1) TableCount,table_schema 
      FROM information_schema.tables 
      WHERE table_schema NOT IN ('information_schema','mysql') 
      GROUP BY table_schema WITH ROLLUP) A;
Nimesh07
quelle
2

Wenn Sie die Datenbank information_schema verwenden, können Sie diesen MySQL-Code verwenden (der where-Teil bewirkt, dass in der Abfrage keine Tabellen mit einem Nullwert für Zeilen angezeigt werden):

SELECT TABLE_NAME, TABLE_ROWS
FROM `TABLES`
WHERE `TABLE_ROWS` >=0
Robin Manoli
quelle
1

Die folgende Abfrage erzeugt eine (weitere) Abfrage, die den Wert von count (*) für jede Tabelle aus jedem in information_schema.tables aufgelisteten Schema erhält. Das gesamte Ergebnis der hier gezeigten Abfrage - alle Zeilen zusammengenommen - enthält eine gültige SQL-Anweisung, die mit einem Semikolon endet - keine baumelnde 'Vereinigung'. Die baumelnde Vereinigung wird durch die Verwendung einer Vereinigung in der folgenden Abfrage vermieden.

select concat('select "', table_schema, '.', table_name, '" as `schema.table`,
                          count(*)
                 from ', table_schema, '.', table_name, ' union ') as 'Query Row'
  from information_schema.tables
 union
 select '(select null, null limit 0);';
user1575139
quelle
1

Dies ist, was ich tue, um die tatsächliche Anzahl zu erhalten (keine Verwendung des Schemas)

Es ist langsamer, aber genauer.

Es ist ein zweistufiger Prozess bei

  1. Holen Sie sich eine Liste der Tabellen für Ihre Datenbank. Sie können es mit bekommen

    mysql -uroot -p mydb -e "show tables"
  2. Erstellen Sie die Liste der Tabellen und weisen Sie sie der Array-Variablen in diesem Bash-Skript zu (getrennt durch ein einzelnes Leerzeichen, genau wie im folgenden Code).

    array=( table1 table2 table3 )
    
    for i in "${array[@]}"
    do
        echo $i
        mysql -uroot mydb -e "select count(*) from $i"
    done
  3. Starte es:

    chmod +x script.sh; ./script.sh
lsaffie
quelle
1

Eine weitere Option: Für Nicht-InnoDB werden Daten aus information_schema.TABLES verwendet (da es schneller ist), für InnoDB wählen Sie count (*), um die genaue Anzahl zu erhalten. Außerdem werden Ansichten ignoriert.

SET @table_schema = DATABASE();
-- or SET @table_schema = 'my_db_name';

SET GROUP_CONCAT_MAX_LEN=131072;
SET @selects = NULL;

SELECT GROUP_CONCAT(
        'SELECT "', table_name,'" as TABLE_NAME, COUNT(*) as TABLE_ROWS FROM `', table_name, '`'
        SEPARATOR '\nUNION\n') INTO @selects
  FROM information_schema.TABLES
  WHERE TABLE_SCHEMA = @table_schema
        AND ENGINE = 'InnoDB'
        AND TABLE_TYPE = "BASE TABLE";

SELECT CONCAT_WS('\nUNION\n',
  CONCAT('SELECT TABLE_NAME, TABLE_ROWS FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND ENGINE <> "InnoDB" AND TABLE_TYPE = "BASE TABLE"'),
  @selects) INTO @selects;

PREPARE stmt FROM @selects;
EXECUTE stmt USING @table_schema;
DEALLOCATE PREPARE stmt;

Wenn Ihre Datenbank viele große InnoDB-Tabellen enthält, kann das Zählen aller Zeilen länger dauern.

Filimonov
quelle
0

So zähle ich TABELLEN und ALLE AUFZEICHNUNGEN mit PHP:

$dtb = mysql_query("SHOW TABLES") or die (mysql_error());
$jmltbl = 0;
$jml_record = 0;
$jml_record = 0;

while ($row = mysql_fetch_array($dtb)) { 
    $sql1 = mysql_query("SELECT * FROM " . $row[0]);            
    $jml_record = mysql_num_rows($sql1);            
    echo "Table: " . $row[0] . ": " . $jml_record record . "<br>";      
    $jmltbl++;
    $jml_record += $jml_record;
}

echo "--------------------------------<br>$jmltbl Tables, $jml_record > records.";
koswara1482
quelle
Warum verwenden Sie nicht count (*), wenn Sie die Daten ignorieren?
Svetoslav Marinov
0

Das Poster wollte die Anzahl der Zeilen ohne zu zählen, gab jedoch nicht an, welche Tabellen-Engine verwendet wurde. Mit InnoDB kenne ich nur einen Weg, nämlich zu zählen.

So pflücke ich meine Kartoffeln:

# Put this function in your bash and call with:
# rowpicker DBUSER DBPASS DBNAME [TABLEPATTERN]
function rowpicker() {
    UN=$1
    PW=$2
    DB=$3
    if [ ! -z "$4" ]; then
        PAT="LIKE '$4'"
        tot=-2
    else
        PAT=""
        tot=-1
    fi
    for t in `mysql -u "$UN" -p"$PW" "$DB" -e "SHOW TABLES $PAT"`;do
        if [ $tot -lt 0 ]; then
            echo "Skipping $t";
            let "tot += 1";
        else
            c=`mysql -u "$UN" -p"$PW" "$DB" -e "SELECT count(*) FROM $t"`;
            c=`echo $c | cut -d " " -f 2`;
            echo "$t: $c";
            let "tot += c";
        fi;
    done;
    echo "total rows: $tot"
}

Ich mache keine Aussagen darüber, außer dass dies ein wirklich hässlicher, aber effektiver Weg ist, um zu ermitteln, wie viele Zeilen in jeder Tabelle in der Datenbank vorhanden sind, unabhängig von der Tabellen-Engine und ohne die Berechtigung zum Installieren gespeicherter Prozeduren und ohne Installation Rubin oder PHP. Ja, es ist rostig. Ja, es zählt. count (*) ist korrekt.

apotek
quelle
0

Basierend auf der obigen Antwort von @ Nathan, aber ohne "die endgültige Vereinigung entfernen zu müssen" und mit der Option, die Ausgabe zu sortieren, verwende ich das folgende SQL. Es wird eine weitere SQL-Anweisung generiert, die dann einfach ausgeführt wird:

select CONCAT( 'select * from (\n', group_concat( single_select SEPARATOR ' UNION\n'), '\n ) Q order by Q.exact_row_count desc') as sql_query
from (
    SELECT CONCAT(
        'SELECT "', 
        table_name, 
        '" AS table_name, COUNT(1) AS exact_row_count
        FROM `', 
        table_schema,
        '`.`',
        table_name, 
        '`'
    ) as single_select
    FROM INFORMATION_SCHEMA.TABLES 
    WHERE table_schema = 'YOUR_SCHEMA_NAME'
      and table_type = 'BASE TABLE'
) Q 

Sie benötigen einen ausreichend großen Wert für die group_concat_max_lenServervariable, aber ab MariaDb 10.2.4 sollte standardmäßig 1 MB verwendet werden.

Adam
quelle
0

Der folgende Code generiert die Auswahlabfrage für alle Geschichten. Löschen Sie einfach das letzte "UNION ALL", wählen Sie alle Ergebnisse aus und fügen Sie ein neues Abfragefenster ein, das ausgeführt werden soll.

SELECT 
concat('select ''', table_name ,''' as TableName, COUNT(*) as RowCount from ' , table_name , ' UNION ALL ')  as TR FROM
information_schema.tables where 
table_schema = 'Database Name'
riesig
quelle
-1

Wenn Sie die genauen Zahlen möchten, verwenden Sie das folgende Ruby-Skript. Sie benötigen Ruby und RubyGems.

Installiere folgende Edelsteine:

$> gem install dbi
$> gem install dbd-mysql

Datei: count_table_records.rb

require 'rubygems'
require 'dbi'

db_handler = DBI.connect('DBI:Mysql:database_name:localhost', 'username', 'password')

# Collect all Tables
sql_1 = db_handler.prepare('SHOW tables;')
sql_1.execute
tables = sql_1.map { |row| row[0]}
sql_1.finish

tables.each do |table_name|
  sql_2 = db_handler.prepare("SELECT count(*) FROM #{table_name};")
  sql_2.execute
  sql_2.each do |row|
    puts "Table #{table_name} has #{row[0]} rows."
  end
  sql_2.finish
end

db_handler.disconnect

Gehen Sie zurück zur Befehlszeile:

$> ruby count_table_records.rb

Ausgabe:

Table users has 7328974 rows.
Michael Voigt
quelle
-4

Wenn Sie die Anzahl der Tabellen und ihre Namen kennen und davon ausgehen, dass sie jeweils Primärschlüssel haben, können Sie einen Cross-Join in Kombination mit verwenden COUNT(distinct [column]), um die Zeilen abzurufen, die aus jeder Tabelle stammen:

SELECT 
   COUNT(distinct t1.id) + 
   COUNT(distinct t2.id) + 
   COUNT(distinct t3.id) AS totalRows
FROM firstTable t1, secondTable t2, thirdTable t3;

Hier ist ein SQL Fiddle- Beispiel.

AdamMc331
quelle