在上週的在 MySQL 中取得進階的列計數(第 2 部分)文章中,我們使用了原生的 COUNT() 函式來計算唯一值以及符合條件的值。在今天的最後一部分中,我們將學習如何從資料庫或整個結構描述中的所有資料表中取得列計數。
查詢 information_schema 資料庫
你不必對每個資料表執行計數查詢以取得列數。如果你計劃多次執行它,這將是繁瑣的並且可能需要外部指令碼。
INFORMATION_SCHEMA 資料庫是每個 MySQL 執行個體儲存有關 MySQL 伺服器維護的所有其他資料庫的資訊的位置。它有時也稱為資料字典和系統目錄,是查閱有關資料庫、資料表、欄的資料類型或存取權限的資訊的理想位置。
INFORMATION_SCHEMA「TABLES」資料表提供有關資料庫中還有哪些資料表的資訊。透過查詢「TABLES」資料表,你可以使用單個查詢取得精確的列計數。
一個資料庫的資料表計數
取得一個資料庫的列計數很容易。只需加入一個 WHERE 子句,其條件是 table_schema 欄符合你的資料庫名稱:
SELECTTABLE_NAME,
TABLE_ROWS
FROM
`information_schema`.`tables`
WHERE
`table_schema` = 'YOUR_DB_NAME';
+------------+------------+
| TABLE_NAME | TABLE_ROWS |
+------------+------------+
| Table1 | 105 |
+------------+------------+
| Table2 | 10299 |
+------------+------------+
| Table3 | 0 |
+------------+------------+
| Table4 | 1045 |
+------------+------------+
整個結構描述的資料表計數
取得結構描述中所有資料庫的列計數需要投入更多的時間量。為此,我們必須使用已備妥的語句。
在語句中,group_concat() 函式將多列打包成一個字串,以便將資料表名稱清單轉換為由等位連接的多個計數的一個字串。
Select-- Sort the tables by count
concat(
'select * from (',
-- Aggregate rows into a single string connected by unions
group_concat(
-- Build a "select count(1) from db.tablename" per table
concat('select ',
quote(db), ' db, ',
quote(tablename), ' tablename, '
'count(1) "rowcount" ',
'from ', db, '.', tablename)
separator ' union ')
, ') t order by 3 desc')
into @sql
from (
select
table_schema db,
table_name tablename
from information_schema.tables
where table_schema not in
('performance_schema', 'mysql', 'information_schema')
) t;
我們的串連 select 語句儲存在 @sql 變數中,以便我們可以將它作為已備妥的語句執行:
-- Execute @sqlprepare s from @sql; execute s; deallocate prepare s;
+-----+-----------+------------+
| db | tablename | rowcount |
+-----+-----------+------------+
| DB1 | Table1 | 1457 |
+-----+-----------+------------+
| DB1 | Table2 | 1029 |
+-----+-----------+------------+
| DB2 | Table1 | 22002 |
+-----+-----------+------------+
| DB2 | Table2 | 1022 |
+-----+-----------+------------+
關於速度和準確度
這些查詢在 MyISAM 資料表上執行得非常快,並產生非常準確的結果。但是,例如 InnoDB 之類的文易儲存引擎不會在資料表中保留內部的列計數。而是,在資料表中取樣許多隨機分頁,然後估計整個資料表的總列數。MVCC(一種允許並行存取列的功能)的後果是,在任何一個時間點,一個列都會有多個版本。因此,實際的 count(1) 將取決於交易開始的時間及其隔離等級。像 InnoDB 這樣的交易儲存引擎,你可以預料其計數的準確度為實際列數的 ±4% 內。