關係資料庫如何快速查詢表的記錄數

来源:http://www.cnblogs.com/kerrycode/archive/2017/05/09/6830970.html
-Advertisement-
Play Games

在資料庫中,很多人員習慣使用SELECT COUNT(*)、SELECT COUNT(1)、SELECT COUNT(COL)來查詢一個表有多少記錄,對於小表,這種SQL的開銷倒不是很大,但是對於大表,這種查詢表記錄數的做法就是一個非常消耗資源了,而且效率很差。下麵介紹一下SQL Server、 O... ...


    在資料庫中,很多人員習慣使用SELECT COUNT(*)、SELECT COUNT(1)、SELECT COUNT(COL)來查詢一個表有多少記錄,對於小表,這種SQL的開銷倒不是很大,但是對於大表,這種查詢表記錄數的做法就是一個非常消耗資源了,而且效率很差。下麵介紹一下SQL Server、 Oracle、MySQL中如何快速獲取表的記錄數。

 

SQL SERVER 資料庫

 

在SQL Server資料庫中, 對象目錄視圖sys.partitions中有一個欄位rows會記錄表的記錄數。我們以AdventureWorks2014為測試資料庫。

 

clip_image001

 

 
SELECT OBJECT_NAME(object_id)    AS Object_Name, 
       i.name                    AS Index_Name,
       p.rows                    AS Table_Rows
FROM sys.partitions  p
LEFT JOIN sys.sysindexes i ON p.object_id = i.id AND  p.index_id = i.indid  
WHERE
     object_id = OBJECT_ID('TableName') 

 

clip_image002

 

那麼我們還有一些疑問,我們先來看看這些問題吧!

 

   1:沒有索引的表是否也可以使用上面腳本?

   2:只有非聚集索引的堆表是否可以使用上面腳本?

   3:有多個索引的表,是否記錄數會存在不一致的情況?

   4:統計信息不准確的表,是否rows也會不准確

   5: 分區表的情況又是怎麼樣?

   6:對象目錄視圖sys.partitions與sp_spaceused獲取的表記錄函數是否準確。

 

如下所示,我們先構造測試案例:

IF EXISTS(SELECT 1 FROM sys.objects WHERE type='U' AND name='TEST_TAB_ROW')
BEGIN
    DROP TABLE TEST_TAB_ROW;
END
 
IF NOT EXISTS(SELECT 1 FROM sys.objects WHERE type='U' AND name='TEST_TAB_ROW')
BEGIN
        CREATE TABLE TEST_TAB_ROW
        (
            ID        INT,
            NAME      CHAR(200)
        )
END
GO
 
SET NOCOUNT ON;
BEGIN TRAN
DECLARE @Index INT =1;
 
WHILE @Index <= 100000
BEGIN
 
    INSERT INTO TEST_TAB_ROW
    VALUES(@Index, NEWID());
 
    SET @Index+=1;
    
    IF (@Index % 5000)  = 0 
       BEGIN
        IF @@TRANCOUNT > 0 
            BEGIN 
                COMMIT;
                BEGIN TRAN
            END
    END
END
 
IF @@TRANCOUNT > 0 
BEGIN 
    COMMIT;
END
GO

 

關於問題1、問題2,都可以使用上面腳本, 如下測試所示:

 

SELECT OBJECT_NAME(object_id)    AS Object_Name, 
       i.name                    AS Index_Name,
       p.rows                    AS Table_Rows
FROM sys.partitions  p
LEFT JOIN sys.sysindexes i ON p.object_id = i.id AND  p.index_id = i.indid  
WHERE
     object_id = OBJECT_ID('dbo.TEST_TAB_ROW') 

clip_image003

 

在表dbo.TEST_TAB_ROW 上創建非聚集索引後,查詢結果如下所示:

 

CREATE INDEX IX_TEST_TAB_ROW ON TEST_TAB_ROW(ID);

 

clip_image004

 

我們插入500條記錄,此時,這個數據量不足以觸發統計信息更新,如下所示, Rows Sampled還是1000000

DECLARE @Index INT =1;
 
WHILE @Index <= 500
BEGIN
 
    INSERT INTO TEST_TAB_ROW
    VALUES(100000 +@Index, NEWID());
 
    SET @Index+=1;
    
END

 

clip_image005

 

如下所示,發現sys.partitions中的記錄變成了100500了,可見rows這個值的計算不依賴統計信息。

 

clip_image006

 

當然,如果你用sp_spaceused,發現這裡面的記錄也是100500

sp_spaceused 'dbo.TEST_TAB_ROW'

clip_image007

 

關於問題3:有多個索引的表,是否記錄數會存在不一致的情況?

 

   答案:個人測試以及統計來看,暫時發現多個索引的情況下,sys.partitions中的rows記錄數都是一致的。暫時沒有發現不一致的情況,當然也不排除有特殊情況。

 

關於問題5: 分區表的情況又是怎麼樣?

 

   答案:分區表和普通表沒有任何區別。

 

關於問題6:對象目錄視圖sys.partitions與sp_spaceused獲取的表記錄函數是否準確?

 

   答案:對象目錄視圖sys.partitions與sp_spaceused獲取的表記錄數是準確的。

 

 

ORACLE 資料庫

 

在ORACLE資料庫中,可以通過DBA_TABLES、ALL_TABLES、USER_TABLES視圖查看表的記錄數,不過這個值(NUM_ROWS)跟統計信息有很大的關係,有時候統計信息沒有更新或採樣比例會導致這個值不是很準確。

SELECT OWNER     , 
       TABLE_NAME, 
       NUM_ROWS  ,
       LAST_ANALYZED
FROM   DBA_TABLES 
WHERE  OWNER = '&OWNER' 
       AND TABLE_NAME = '&TABLE_NAME'; 
 
 
SELECT OWNER,
      TABLE_NAME,
      NUM_ROWS  ,
      LAST_ANALYZED
FROM ALL_TABLES
WHERE OWNER   ='&OWNER'
AND TABLE_NAME='&TABLE_NAME';
 
 
SELECT TABLE_NAME,
       NUM_ROWS  ,
       LAST_ANALYZED
FROM USER_TABLES
WHERE TABLE_NAME='&TABLE_NAME'

 

更新統計信息後,就能得到準確的行數。所以如果需要得到正確的數據,最好更新目標表的統計信息,進行100%採樣分析。對於分區表,那麼就需要從dba_tab_partitions裡面查詢相關數據了。

 

SQL>execute dbms_stats.gather_table_stats(ownname => 'username', tabname =>'tablename', estimate_percent =>100, cascade=>true);

 

MySQL資料庫

 

   在MySQL中比較特殊,雖然INFORMATION_SCHEMA.TABLES也可以查到表的記錄數,但是非常不准確。如下所示,即使使用ANALYZE TABLE更新了統計信息,從INFORMATION_SCHEMA.TABLES中獲取的記錄依然不准確。

SELECT TABLE_ROWS 
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='table_name'

 

mysql> SELECT TABLE_ROWS 
    -> FROM INFORMATION_SCHEMA.TABLES
    -> WHERE TABLE_NAME='jiraissue'
	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 入行快10年,有點積蓄,三年前買了代步車。於是乎,汽車油耗開銷就成了每個月都必須關註的問題。三年來,用過了無數油耗記錄軟體,比如最知名的“小熊油耗”,從第一次用,一直到最新一版,感覺越來越“臃腫”,功能實在是太豐富了,甚至都做到“大數據”這一層面,作為一個小白車主,其實,我只關心:我的車油耗如何。 ...
  • RunLoop是iOS線程相關的比較重要的一個概念,無論是主線程還是子線程,都對應一個RunLoop,如果沒有RunLoop,線程會馬上被系統回收。 本文主要CFRunLoop的源碼解析,並簡單闡述一下CFRunLoop的原理。 CFRunLoop是開源的,開源地址在:http://opensour ...
  • //將字元串轉化成Drawable public synchronized static Drawable StringToDrawable(String icon) { if (icon == null || icon.length() < 10) return null; byte[] img ... ...
  • 小狼咕咕最近開啟了微信小程式開發的徵程,由於微信小程式的前後臺通信必須通過https協議,所以小狼咕咕第一件要做的事就是配置一個能夠通過https訪問的後臺服務。小狼咕咕用的是阿裡雲ECS伺服器,Linux系統,安裝的tomcat。 打開阿裡雲盾——CA證書服務,找不到的朋友也可以在下圖的菜單中直接 ...
  • 如果轉載,請註明博文來源: www.cnblogs.com/xinysu/ ,版權歸 博客園 蘇家小蘿蔔 所有。望各位支持! 1 行記錄如何存儲 這裡引入兩個概念:堆跟聚集索引表。本部分參考MSDN。 1.1 堆表 堆表,沒有聚集索引的表格,可以創建一個或者多個非聚集索引。沒有按照某個規則進行存儲, ...
  • 一.準備教程 1.jdk:版本在1.7.x以上就可以(因為hadoop2.x以上只支持1.7.x以上的jdk,我的是1.8的) 2.Hadoop:2.7.3 二.ssh的配置以及驗證 配置ssh: 1.確認mac的遠程登錄是否開啟 系統偏好設置->共用->勾選遠程登錄. 當遠程登錄狀態為打開且為綠燈 ...
  • 表分區是一種思想,分區表示一種技術實現。當表的大小過G的時候可以考慮進行表分區,提高查詢效率,均衡IO。oracle分區表是oracle資料庫提供的一種表分區的實現形式。表進行分區後,邏輯上仍然是一張表,原來的查詢SQL同樣生效,同時可以採用使用分區查詢來優化SQL查詢效率,不至於每次都掃描整個表。 ...
  • 前段時間一個測試環境的mysql資料庫的root密碼找不到了,一個不重要的庫,安裝人員估計疏忽了...手動把密碼恢復了一下。記錄下來做個備註 1、進入my.cnf ,在[mysqld]欄位中添加 skip-grant-tables 2、重啟mysql服務 service mysqld restart ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...