我遇到的文章表明,SELECT COUNT(*) FROM TABLE_NAME
当表有很多行和很多列时会很慢.
我有一个表可能包含数十亿行[它有大约15列].有没有更好的方法来获得表的行数的精确计数?
请在回答之前考虑以下事项:
我正在寻找独立于数据库供应商的解决方案.如果它涵盖MySQL,Oracle,MS SQL Server,那就没关系.但如果确实没有数据库供应商独立解决方案,那么我将为不同的数据库供应商寻求不同的解决方案.
我不能使用任何其他外部工具来做到这一点.我主要是在寻找基于SQL的解决方案.
我无法进一步规范我的数据库设计.它已经在3NF,而且已经编写了很多代码.
gbn*_*gbn 231
简单回答:
COUNT(*)
笔记:
COUNT(1)= COUNT(*)= COUNT(PrimaryKey)以防万一
编辑:
SQL Server示例(14亿行,12列)
SELECT COUNT(*) FROM MyBigtable WITH (NOLOCK)
-- NOLOCK here is for me only to let me test for this answer: no more, no less
Run Code Online (Sandbox Code Playgroud)
1次运行,5:46分钟,计数= 1,401,659,700
--Note, sp_spaceused uses this DMV
SELECT
Total_Rows= SUM(st.row_count)
FROM
sys.dm_db_partition_stats st
WHERE
object_name(object_id) = 'MyBigtable' AND (index_id < 2)
Run Code Online (Sandbox Code Playgroud)
2次运行,均低于1秒,计数= 1,401,659,670
第二个有较少的行=错误.取决于写入将是相同或更多(删除是在几小时内完成的)
sal*_*hra 25
到目前为止,MySQL上最快的方法是:
SHOW TABLE STATUS;
Run Code Online (Sandbox Code Playgroud)
如果需要,您将立即获得包含行数(即总数)的所有表格以及大量额外信息.
Jak*_*keJ 18
我从另一个 StackOverflow 问题/答案中得到了这个脚本:
SELECT SUM(p.rows) FROM sys.partitions AS p
INNER JOIN sys.tables AS t
ON p.[object_id] = t.[object_id]
INNER JOIN sys.schemas AS s
ON s.[schema_id] = t.[schema_id]
WHERE t.name = N'YourTableNameHere'
AND s.name = N'dbo'
AND p.index_id IN (0,1);
Run Code Online (Sandbox Code Playgroud)
我的表有 5 亿条记录,上面的返回时间不到 1 毫秒。同时,
SELECT COUNT(id) FROM MyTable
Run Code Online (Sandbox Code Playgroud)
耗时整整 39 分 52 秒!
它们产生完全相同的行数(在我的例子中,正好是 519326012)。
我不知道是否会一直如此。
Den*_*rdy 10
我遇到过一些文章,指出当表有很多行和很多列时,SELECT COUNT(*)FROM TABLE_NAME会很慢.
这取决于数据库.一些加速计数,例如通过跟踪索引中的行是活的还是死的,允许仅索引扫描来提取行数.其他人则没有,因此需要访问整个表格并逐个计算实时行.一个巨大的桌子要么慢.
请注意,您通常可以通过使用查询优化工具,表统计信息等来提取良好的估计值.例如,在PostgreSQL的情况下,您可以解析输出explain count(*) from yourtable
并获得相当好的行数估计.这让我想到了你的第二个问题.
我有一个表可能包含数十亿行[它有大约15列].有没有更好的方法来获得表的行数的精确计数?
真的吗?:-)你真的是指数十亿行的表中的确切数量?你真的相信吗?:-)
如果你真的这样做,你可以保留一下总的使用触发器,但如果你这样做,请注意并发和死锁.
你可以试试这个sp_spaceused(Transact-SQL)
显示当前数据库中的表,索引视图或Service Broker队列使用的行数,保留的磁盘空间和磁盘空间,或显示整个数据库保留和使用的磁盘空间.
有没有更好的方法来获得表的行数的精确计数?
简单地回答你的问题,不.
如果您需要以DBMS独立的方式执行此操作,最快的方法将始终是:
SELECT COUNT(*) FROM TableName
Run Code Online (Sandbox Code Playgroud)
一些DBMS供应商可能有更快的方法,只适用于他们的系统.其中一些选项已经发布在其他答案中.
COUNT(*)
应该由DBMS(至少任何PROD值得的数据库)优化,所以不要试图绕过他们的优化.
请注意:
我确信您的许多其他查询也需要很长时间才能完成,因为您的表格大小.任何性能问题都应该通过考虑速度考虑您的架构设计来解决.我意识到你说它不是一个改变的选择,但它可能会发现10分钟以上的查询也不是一个选择.3 NF并不总是最好的方法,当你需要的速度,有时数据可以在多个表中,如果记录不就被划分具有存储在一起.需要考虑的事情......
如果SQL Server版本为2005/2008,则可以使用DMV计算表中的行数:
-- Shows all user tables and row counts for the current database
-- Remove is_ms_shipped = 0 check to include system objects
-- i.index_id < 2 indicates clustered index (1) or hash table (0)
SELECT o.name,
ddps.row_count
FROM sys.indexes AS i
INNER JOIN sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID
INNER JOIN sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID
AND i.index_id = ddps.index_id
WHERE i.index_id < 2
AND o.is_ms_shipped = 0
ORDER BY o.NAME
Run Code Online (Sandbox Code Playgroud)
对于SQL Server 2000数据库引擎,可以使用sysindexes,但强烈建议避免在SQL Server的将来版本中使用它,因为它可能会在不久的将来删除。
示例代码取自:如何快速而无痛地获取表行计数
我发现这篇好文章SQL Server–HOW-TO:快速检索表的准确行数,从中martijnh1
可以很好地概括每个场景。
我需要在需要根据特定条件提供计数的地方对此进行扩展,当我计算出这部分时,我将进一步更新此答案。
同时,以下是文章的详细信息:
方法一:
询问:
SELECT COUNT(*) FROM Transactions
Run Code Online (Sandbox Code Playgroud)
注释:
执行全表扫描。在大桌子上慢。
方法二:
询问:
SELECT CONVERT(bigint, rows)
FROM sysindexes
WHERE id = OBJECT_ID('Transactions')
AND indid < 2
Run Code Online (Sandbox Code Playgroud)
注释:
检索行数的快速方法。取决于统计数据并且不准确。
运行 DBCC UPDATEUSAGE(Database) WITH COUNT_ROWS,这对于大型表来说可能需要很长时间。
方法三:
询问:
SELECT CAST(p.rows AS float)
FROM sys.tables AS tbl
INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and
idx.index_id < 2
INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int)
AND p.index_id=idx.index_id
WHERE ((tbl.name=N'Transactions'
AND SCHEMA_NAME(tbl.schema_id)='dbo'))
Run Code Online (Sandbox Code Playgroud)
注释:
SQL 管理工作室计算行数的方式(查看表属性、存储、行数)。非常快,但仍然是大约的行数。
方法四:
询问:
SELECT SUM (row_count)
FROM sys.dm_db_partition_stats
WHERE object_id=OBJECT_ID('Transactions')
AND (index_id=0 or index_id=1);
Run Code Online (Sandbox Code Playgroud)
注释:
快速(虽然不如方法 2 快)操作和同样重要、可靠。
小智 5
我用
select /*+ parallel(a) */ count(1) from table_name a;
Run Code Online (Sandbox Code Playgroud)
我已经远远不及那些已经回答的其他人,但是我遇到的问题是我用来从表中选择一个随机行(不过度相关),但我需要知道我的参考表中的行数计算随机指数.使用传统的Count(*)或Count(1)工作,但偶尔我的查询运行时间最长为2秒.所以相反(我的名为'tbl_HighOrder'的表)我正在使用:
Declare @max int
Select @max = Row_Count
From sys.dm_db_partition_stats
Where Object_Name(Object_Id) = 'tbl_HighOrder'
Run Code Online (Sandbox Code Playgroud)
它工作得很好,Management Studio中的查询时间为零.
好吧,晚了5年,不确定是否有帮助:
我试图数数。MS SQL Server Management Studio的SQL Server表中的行数,并遇到一些溢出错误,然后使用以下代码:
从[dbname]。[dbo]中选择count_big(1)。[FactSampleValue];
结果 :
24296650578行