SELECT count()
Her tabloda bir çalıştırma yapmadan MySQL veritabanındaki tüm tablolardaki satır sayısını almanın bir yolu var mı ?
SELECT count()
Her tabloda bir çalıştırma yapmadan MySQL veritabanındaki tüm tablolardaki satır sayısını almanın bir yolu var mı ?
Yanıtlar:
SELECT SUM(TABLE_ROWS)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '{your_db}';
Yine de dokümanlardan not: InnoDB tabloları için satır sayısı SQL optimizasyonunda kullanılan kabaca bir tahmindir . Tam sayımlar için COUNT (*) kullanmanız gerekir (bu daha pahalıdır).
Muhtemelen Tablolar tablosu ile bir şeyler koyabilirsiniz . Bunu hiç yapmadım, ancak TABLE_ROWS için bir sütun ve TABLE NAME için bir sütun var gibi görünüyor .
Tablo başına satır almak için aşağıdaki gibi bir sorgu kullanabilirsiniz:
SELECT table_name, table_rows
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '**YOUR SCHEMA**';
@Venkatramanan ve diğerleri gibi, bilgi tablolarında bile her çalıştırdığımda farklı satır sayıları vererek BİLGİ_SCHEMA.TABLES'i güvenilmez buldum (InnoDB, MySQL 5.1.44 kullanarak). İşte Ruby taşlar ve şeyler yüklemeden yeni bir sorguya yapıştırabileceğiniz büyük bir SQL ifadesi oluşturmanın nispeten sert (ancak esnek / uyarlanabilir) bir yolu.
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**';
Bunun gibi çıktılar üretir:
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
Gibi güzel çıktılar almak için son UNION dışında kopyalayıp yapıştırın,
+------------------+-----------------+
| 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)
Sadece koşuyorum:
show table status;
Bu size HER tablo için satır sayısı artı bir dizi başka bilgi verecektir. Yukarıda seçilen cevabı kullanırdım, ama bu çok daha kolay.
Bunun tüm sürümlerle çalışıp çalışmadığından emin değilim, ancak InnoDB motoruyla 5.5 kullanıyorum.
SELECT TABLE_NAME,SUM(TABLE_ROWS)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'your_db'
GROUP BY TABLE_NAME;
Tek ihtiyacınız olan bu.
mysql> SELECT TABLE_NAME,SUM(TABLE_ROWS) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ngramsdb' GROUP BY TABLE_NAME;
Bu saklı yordam tabloları listeler, kayıtları sayar ve sonunda toplam kayıt sayısı üretir.
Bu yordamı ekledikten sonra çalıştırmak için:
CALL `COUNT_ALL_RECORDS_BY_TABLE` ();
-
Prosedür:
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
Basit yol:
SELECT
TABLE_NAME, SUM(TABLE_ROWS)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '{Your_DB}'
GROUP BY TABLE_NAME;
Sonuç örneği:
+----------------+-----------------+
| 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 |
+----------------+-----------------+
Bu tahminde bulunma sorununun bir kesilmesi / çözümü vardır.
Auto_Increment - herhangi bir nedenle, tablolarda otomatik artış ayarladıysanız, veritabanınız için çok daha doğru bir satır sayısı döndürür.
Şov tablosu bilgisinin neden gerçek verilerle eşleşmediğini keşfederken bunu buldum.
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)
Daha sonra kolayca PHP veya satır sayısı için "en iyi tahmin" vermek için 2 veri sütunlarının maksimum döndürmek için ne olursa olsun kullanabilirsiniz.
yani
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;
Otomatik Artış her zaman +1 * (tablo sayısı) satırlar kapalı olacaktır, ancak 4.000 tablo ve 3 milyon satırla bile, bu% 99,9 doğrudur. Tahmin edilen satırlardan çok daha iyi.
Bunun güzelliği, performance_schema'da döndürülen satır sayımlarının sizin için de silinmesidir, çünkü en büyüğü boşta çalışmaz. Otomatik artışlı tablolarınız yoksa bu bir sorun olabilir.
İnfo_schema veritabanı kullanıyorsanız, bu mysql kodunu kullanabilirsiniz (burada bölüm sorguyu satırlar için boş değeri olan tabloları göstermez):
SELECT TABLE_NAME, TABLE_ROWS
FROM `TABLES`
WHERE `TABLE_ROWS` >=0
Aşağıdaki sorgu, information_schema.tables içinde listelenen her şemadan, her tablo için count (*) değerini alacak bir (nother) sorgu üretir. Burada gösterilen sorgunun tüm sonucu - birlikte alınan tüm satırlar - noktalı virgülle biten geçerli bir SQL ifadesi içerir - sarkan 'birleşim' yoktur. Sarkan sendika, aşağıdaki sorguda bir sendika kullanılarak önlenir.
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);';
Bu gerçek sayımı almak için yaptığım şeydir (şemayı kullanmadan)
Daha yavaş ama daha doğru.
Bu iki adımlı bir süreçtir.
Db için tabloların listesini alın. Kullanarak alabilirsiniz
mysql -uroot -p mydb -e "show tables"
Bu bash betiğindeki dizi değişkenine tablo listesini oluşturun ve atayın (aşağıdaki kodda olduğu gibi tek bir boşlukla ayrılmış)
array=( table1 table2 table3 )
for i in "${array[@]}"
do
echo $i
mysql -uroot mydb -e "select count(*) from $i"
done
Çalıştır:
chmod +x script.sh; ./script.sh
Bir seçenek daha: InnoDB olmayanlar için, information_schema.TABLES (daha hızlı olduğu gibi) verilerini kullanır, InnoDB için - doğru sayımı elde etmek için sayımı (*) seçin. Ayrıca görünümleri yok sayar.
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;
Veritabanınızda çok sayıda büyük InnoDB tablosu varsa, tüm satırları saymak daha fazla zaman alabilir.
Ben PHP kullanarak TABLOLAR ve TÜM KAYIT saymak budur:
$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.";
Poster, saymadan satır sayımı istedi, ancak hangi tablo motorunu belirtmedi. InnoDB ile, sadece bir yol biliyorum, bu sayılacak.
Patateslerimi şu şekilde seçiyorum:
# 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"
}
Bu konuda herhangi bir iddia yapıyorum, bu gerçekten çirkin ama etkili bir yolu var ne kadar tablo motoru ne olursa olsun veritabanında her tabloda kaç satır var saklı yordamlar yükleme izni gerek kalmadan ve yüklemeye gerek kalmadan yakut veya php. Evet, paslı. Evet önemlidir. count (*) doğrudur.
Yukarıdaki @ Nathan'ın cevabına dayanarak, "son birliği kaldırmaya" gerek kalmadan ve çıktıyı sıralama seçeneğiyle aşağıdaki SQL'i kullanıyorum. Daha sonra sadece çalışan başka bir SQL ifadesi oluşturur:
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
group_concat_max_len
Sunucu değişkeninin yeterince büyük bir değerine ihtiyacınız vardır, ancak MariaDb 10.2.4 sürümünden varsayılan olarak 1M olmalıdır.
Aşağıdaki kod, tüm masallar için seçme sorgusu oluşturur. Sadece son "UNION ALL" tüm sonucu seçin ve çalıştırmak için yeni bir sorgu penceresi yapıştırın.
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'
Kesin sayıları istiyorsanız, aşağıdaki yakut komut dosyasını kullanın. Ruby ve RubyGems'e ihtiyacınız var.
Aşağıdaki Gems yükleyin:
$> gem install dbi
$> gem install dbd-mysql
Dosya: 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
Komut satırına geri dönün:
$> ruby count_table_records.rb
Çıktı:
Table users has 7328974 rows.
Tablo sayısını ve adlarını biliyorsanız ve her birinin birincil anahtarları olduğunu varsayarsak COUNT(distinct [column])
, her bir tablodan gelen satırları almak için ile birlikte bir birleştirme kullanabilirsiniz :
SELECT
COUNT(distinct t1.id) +
COUNT(distinct t2.id) +
COUNT(distinct t3.id) AS totalRows
FROM firstTable t1, secondTable t2, thirdTable t3;
İşte bir SQL Fiddle örneği.