mysql 每条记录大小_计算数据库中各个表的数据量和每行记录所占用空间
很多時(shí)候我們都需要計(jì)算數(shù)據(jù)庫中各個表的數(shù)據(jù)量和每行記錄所占用空間
這里共享一個腳本
CREATE TABLE #tablespaceinfo
(
nameinfo VARCHAR(500) ,
rowsinfo BIGINT ,
reserved VARCHAR(20) ,
datainfo VARCHAR(20) ,
index_size VARCHAR(20) ,
unused VARCHAR(20)
)
DECLARE @tablename VARCHAR(255);
DECLARE Info_cursor CURSOR
FOR
SELECT '[' + [name] + ']'
FROM sys.tables
WHERE type = 'U';
OPEN Info_cursor
FETCH NEXT FROM Info_cursor INTO @tablename
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO #tablespaceinfo
EXEC sp_spaceused @tablename
FETCH NEXT FROM Info_cursor
INTO @tablename
END
CLOSE Info_cursor
DEALLOCATE Info_cursor
--創(chuàng)建臨時(shí)表
CREATE TABLE [#tmptb]
(
TableName VARCHAR(50) ,
DataInfo BIGINT ,
RowsInfo BIGINT ,
Spaceperrow AS ( CASE RowsInfo
WHEN 0 THEN 0
ELSE DataInfo / RowsInfo
END ) PERSISTED
)
--插入數(shù)據(jù)到臨時(shí)表
INSERT INTO [#tmptb]
( [TableName] ,
[DataInfo] ,
[RowsInfo]
)
SELECT [nameinfo] ,
CAST(REPLACE([datainfo], 'KB', '') AS BIGINT) AS 'datainfo' ,
[rowsinfo]
FROM #tablespaceinfo
ORDER BY CAST(REPLACE(reserved, 'KB', '') AS INT) DESC
--匯總記錄
SELECT [tbspinfo].* ,
[tmptb].[Spaceperrow] AS '每行記錄大概占用空間(KB)'
FROM [#tablespaceinfo] AS tbspinfo ,
[#tmptb] AS tmptb
WHERE [tbspinfo].[nameinfo] = [tmptb].[TableName]
ORDER BY CAST(REPLACE([tbspinfo].[reserved], 'KB', '') AS INT) DESC
DROP TABLE [#tablespaceinfo]
DROP TABLE [#tmptb]
注意:使用之前要計(jì)算哪個數(shù)據(jù)庫的記錄,請先USE一下要統(tǒng)計(jì)表記錄數(shù)的那個數(shù)據(jù)庫!!
工作中遇到的問題
可以說我在實(shí)際的工作中 ,在100個問題中有90個都會先用到這個腳本
這里舉一個我本人工作中遇到的一些問題
問題一:
程序員反映數(shù)據(jù)庫查詢慢,5分鐘還沒有出結(jié)果
我先用這個腳本看一下這個表有多少記錄,大概有1000w+條數(shù)據(jù)
然后在本地的SSMS里查詢,確實(shí)也是大概4分鐘的樣子才出來數(shù)據(jù),看一下執(zhí)行計(jì)劃,發(fā)現(xiàn)查詢能使用到索引
看一下數(shù)據(jù)庫的壓力,并不是很大,我跟會不會跟數(shù)據(jù)量有關(guān)系呢?
程序員要查詢的結(jié)果條數(shù)是500條數(shù)據(jù),業(yè)務(wù)表是做了分區(qū)的,按道理應(yīng)該不會慢成這樣。。。
后來我再看一下共享出來的那個腳本的結(jié)果,發(fā)現(xiàn)查詢的結(jié)果大小=每行記錄的大小*記錄數(shù)
要查詢大概500MB的數(shù)據(jù),再傳到客戶端,不慢才怪
為什麼查詢出的結(jié)果這么大?
主要是有幾個大字段:例如:二進(jìn)制字段和NVARCHAR(MAX)
并且時(shí)間范圍跨度比較大
馬上叫程序員改一下查詢的語句,由于是entity framework程序,怎麼改我就不太清楚了,主要是不必要的字段就不查詢處理并且縮小時(shí)間范圍
問題二:
還有一些問題也需要知道每行記錄的大小,例如刪除表的歷史數(shù)據(jù),QA說要保留2013年之前的數(shù)據(jù),你需要查出保留的數(shù)據(jù)或者2013年之前的數(shù)據(jù)占用多少G空間
再結(jié)合當(dāng)前服務(wù)器的磁盤可用空間,來評估刪除的數(shù)據(jù)是否太多或者太少
那么流程是:先查出2013年之前的記錄數(shù)有多少-》計(jì)算表的總記錄數(shù)-》計(jì)算表的大小-》手工計(jì)算每行記錄的大小-》乘以2013年之前的記錄數(shù)
如果沒有每行記錄數(shù)這個字段,那么你手工計(jì)算,是不是效率就變慢了???
問題三:
導(dǎo)數(shù)據(jù)的時(shí)候,你想知道當(dāng)前已經(jīng)導(dǎo)了多少數(shù)據(jù)了,那么執(zhí)行一下這個腳本就可以了,這個腳本基本不會被阻塞
很快就能查出結(jié)果
腳本的計(jì)算方法
方法一
實(shí)際上利用的就是數(shù)據(jù)行大小的信息除以記錄數(shù)
CASE RowsInfo
WHEN 0 THEN 0
ELSE DataInfo / RowsInfo
方法二
SELECT AVG(DATALENGTH(C0))+AVG(DATALENGTH(C1))+AVG(DATALENGTH(C2))+AVG(DATALENGTH(C3)) FROM [dbo].[TB106]
說一下兩種方法的區(qū)別
第一種方法是效率高,當(dāng)表有上億條記錄的時(shí)候,如果你使用第二種方法執(zhí)行AVG(DATALENGTH(C0))是很慢的,因?yàn)镾QLSERVER要統(tǒng)計(jì)字段大小信息
可能十幾分鐘都出不來結(jié)果
當(dāng)然,第一種方法也有一些缺陷,就是當(dāng)表的記錄數(shù)少的時(shí)候,統(tǒng)計(jì)出來的每行記錄占用空間是不準(zhǔn)確的
因?yàn)閐atainfo這個值是以數(shù)據(jù)頁大小為單位的,因?yàn)榫退惚碇挥幸粭l記錄,那么也會占用一個數(shù)據(jù)頁(8KB)
那么當(dāng)8KB/1 =8KB,一條記錄肯定不會是8KB大小的,所以記錄少的時(shí)候會不準(zhǔn)確
但是當(dāng)記錄數(shù)很多的時(shí)候,就準(zhǔn)確了
看一下TB106這個表統(tǒng)計(jì)出來的結(jié)果值
SELECT AVG(DATALENGTH(C0))+AVG(DATALENGTH(C1))+AVG(DATALENGTH(C2))+AVG(DATALENGTH(C3)) FROM [dbo].[TB106]
可以看到是比較準(zhǔn)確的
注意:
無論方法一還是方法二都不包括索引所占用的空間 !!
總結(jié)
大家平時(shí)一定會想:究竟DBA有什么作用?
在這里就給大家一個例子了,在工作中,程序員是不會關(guān)心他要查詢的數(shù)據(jù)的大小的,他不管三七二十一只要把數(shù)據(jù)select出來就行了,然后收工
DBA這里就要解決數(shù)據(jù)查詢不出來的問題,一般的程序員覺得查詢500條數(shù)據(jù)是很少的,根本不會關(guān)心表設(shè)計(jì),表的字段的數(shù)據(jù)類型
當(dāng)工作越來越多,開發(fā)任務(wù)越來越重的時(shí)候更是這樣
所以本人覺得DBA這個角色還是比較重要的o(∩_∩)o
如有不對的地方,歡迎大家拍磚o(∩_∩)o
2014-7-7 腳本bug修復(fù)
由于算出來每行記錄的精度有問題,我又對腳本的精度進(jìn)行了改進(jìn)
CREATE TABLE #tablespaceinfo
(
nameinfo VARCHAR(500) ,
rowsinfo BIGINT ,
reserved VARCHAR(20) ,
datainfo VARCHAR(20) ,
index_size VARCHAR(20) ,
unused VARCHAR(20)
)
DECLARE @tablename VARCHAR(255);
DECLARE Info_cursor CURSOR
FOR
SELECT '[' + [name] + ']'
FROM sys.tables
WHERE type = 'U';
OPEN Info_cursor
FETCH NEXT FROM Info_cursor INTO @tablename
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO #tablespaceinfo
EXEC sp_spaceused @tablename
FETCH NEXT FROM Info_cursor
INTO @tablename
END
CLOSE Info_cursor
DEALLOCATE Info_cursor
--創(chuàng)建臨時(shí)表
CREATE TABLE [#tmptb]
(
TableName VARCHAR(50) ,
DataInfo BIGINT ,
RowsInfo BIGINT ,
Spaceperrow AS ( CASE RowsInfo
WHEN 0 THEN 0
ELSE CAST(DataInfo AS decimal(18,2))/CAST(RowsInfo AS decimal(18,2))
END ) PERSISTED
)
--插入數(shù)據(jù)到臨時(shí)表
INSERT INTO [#tmptb]
( [TableName] ,
[DataInfo] ,
[RowsInfo]
)
SELECT [nameinfo] ,
CAST(REPLACE([datainfo], 'KB', '') AS BIGINT) AS 'datainfo' ,
[rowsinfo]
FROM #tablespaceinfo
ORDER BY CAST(REPLACE(reserved, 'KB', '') AS INT) DESC
--匯總記錄
SELECT [tbspinfo].* ,
[tmptb].[Spaceperrow] AS '每行記錄大概占用空間(KB)'
FROM [#tablespaceinfo] AS tbspinfo ,
[#tmptb] AS tmptb
WHERE [tbspinfo].[nameinfo] = [tmptb].[TableName]
ORDER BY CAST(REPLACE([tbspinfo].[reserved], 'KB', '') AS INT) DESC
DROP TABLE [#tablespaceinfo]
DROP TABLE [#tmptb]
總結(jié)
以上是生活随笔為你收集整理的mysql 每条记录大小_计算数据库中各个表的数据量和每行记录所占用空间的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于通配泛型类型有几种_5.7 泛型通配
- 下一篇: mysql快捷创建数据库_mysql数据