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 ?
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 ?
Antworten:
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).
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**';
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)
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.
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.
mysql> SELECT TABLE_NAME,SUM(TABLE_ROWS) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ngramsdb' GROUP BY TABLE_NAME;
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
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 |
+----------------+-----------------+
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.
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;
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
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);';
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
Holen Sie sich eine Liste der Tabellen für Ihre Datenbank. Sie können es mit bekommen
mysql -uroot -p mydb -e "show tables"
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
Starte es:
chmod +x script.sh; ./script.sh
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.
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.";
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.
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_len
Servervariable, aber ab MariaDb 10.2.4 sollte standardmäßig 1 MB verwendet werden.
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'
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.
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.