什么可以加快SQL计数查询的速度?


9

在进行计数(总计)SQL查询时,什么可以加快这3个数据库系统的执行时间?我敢肯定,有很多事情可以加快它的速度(硬件就是其中之一),但是我只是DBA的新手,所以我确定我会在这里得到一些答案。我将大约1.57亿行迁移到了SQL Server数据库,而这种查询将永远持续下去。但是在我的源Netezza数据库中,它需要几秒钟。

例如:

Netezza 6:

SELECT COUNT(*) FROM DATABASENAME..MYTABLE

Oracle 11g:

SELECT COUNT(*) FROM MYTABLE

SQL Server 2012:

SELECT COUNT(*) FROM DATABASENAME.[dbo].[MYTABLE]


1
您只需要执行一次还是重复一次?
乔恩·塞格尔

@JonSeigel我们正在执行增量加载,并且每天都要比较数据库系统之间的记录,以确保计数加起来。如此反复。
MacGyver 2012年

Answers:


10

Netezza是一种旨在在大型表扫描方面表现出色的设备,因此这就是在该系统上获得如此快速的结果的原因。

对于您的SQL Server,可以通过从sys.dm_db_partition_stats DMV中进行查询来大大加快行数。

SELECT s.name AS [Schema], o.name AS [Table], SUM(p.row_count) AS [RowCount]
FROM sys.dm_db_partition_stats p JOIN sys.objects o
ON p.object_id = o.object_id JOIN sys.schemas s
ON o.schema_id = s.schema_id
WHERE p.index_id < 2
AND o.object_id = object_id('MyTable')
GROUP BY o.name, s.name;

在高交易环境中,不能保证此DMV是100%准确的。但是从您的问题来看,似乎您只是在进行行计数以在迁移后验证每个表,因此此查询应该对您有用。


4
@Phil为什么?如果您遍历表并从每个表中执行昂贵的SELECT COUNT(*)-到达最后一个表后,第一个结果的准确性如何?
亚伦·伯特兰

1
为了清楚起见,菲尔曾说过:“使用数据字典,它不能提供100%准确的结果,这是个坏建议。我认为答案应该被编辑以删除建议或删除-记住人们在谷歌上寻找答案,并且会盲目地剪切并粘贴...”我同意免责声明很重要(据称在某些极端情况下,元数据没有返回有意义的结果),我不同意通常使用元数据视图是不好的建议。
亚伦·伯特兰

5

这是COUNT_BIG在索引视图中使用的SQL Server解决方案。这将为您提供事务一致的计数,而无需大表扫描或索引扫描的开销,也无需后者所需的存储空间:

CREATE TABLE [dbo].[MyTable](id int);
GO

CREATE VIEW [dbo].[MyTableRowCount]
    WITH SCHEMABINDING
AS

    SELECT
        COUNT_BIG(*) AS TableRowCount
        FROM [dbo].[MyTable];
GO

CREATE UNIQUE CLUSTERED INDEX IX_MyTableRowCount
    ON [dbo].[MyTableRowCount](TableRowCount);
GO

SELECT
    TableRowCount
    FROM [dbo].[MyTableRowCount] WITH(NOEXPAND);

这将需要进行一次初始扫描(无法摆脱这种情况),并为增量表数据操作增加了一些开销。如果您要对大量数据进行大型操作(与许多小型操作相对),那么我认为更改的开销应该可以忽略不计。


@SQLKiwi:2012年之前如何阻止读取?SQL Server错误?
乔恩·塞格尔

@JonSeigel-我的$ 0,05:离线创建的普通表上的普通聚簇索引在表上应用了Sch-M锁。在视图上,当然是不需要的,但这意味着对Create Index操作的更改,以为索引视图创建特例-这是对SQL2012所做的。恕我直言,当然。
Fabricio Araujo 2012年

3

在Oracle中,NOT NULL列上的二叉树索引可用于回答COUNT(*)。在大多数情况下,它比FULL TABLE SCAN更快,因为索引通常小于其基表。

但是,常规的二叉树索引仍然非常庞大,只有157个Mrows。如果您的表不是同时更新的(即仅批量加载过程),那么您可能想使用位图索引。

最小的位图索引如下所示:

CREATE BITMAP INDEX ix ON your_table(NULL);

空条目由位图索引考虑。与常规二叉树索引或基表相比,结果索引将很小(每百万行20-30个8k块)。

生成的计划应显示以下操作:

----------------------------------------------
| Id  | Operation                     | Name | 
----------------------------------------------
|   0 | SELECT STATEMENT              |      |
|   1 |  SORT AGGREGATE               |      |
|   2 |   BITMAP CONVERSION COUNT     |      |
|   3 |    BITMAP INDEX FAST FULL SCAN| IX   |
----------------------------------------------

如果您的表是同时更新的,则具有唯一值的位图索引将成为争用点,因此不应使用。


3

在Oracle中,通常通过扫描索引而不是整个表来执行简单计数查询。索引必须是位图索引或在具有NOT NULL约束的列上定义。对于需要全表扫描的更复杂的查询,可以使用并行查询。

要启用并行查询(需要企业版),可以使用优化器提示:

select /*+ PARALLEL(mytable, 12) */ count(*) from mytable;

或为表上的所有查询启用并行查询:

alter table mytable parallel 12;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.