首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >表中的列数是否会影响没有索引的表上的count(*)查询的性能?

表中的列数是否会影响没有索引的表上的count(*)查询的性能?
EN

Stack Overflow用户
提问于 2014-10-24 20:30:04
回答 1查看 5.2K关注 0票数 3

我正在创建基准表来测量Netezza框上的每小时负载(查询延迟、查询持续时间)。我对表中想要的行数有一个合理的了解,并且我正在试图决定列的数目。没有索引;我将运行完整的表扫描。

我试图确定基准表中需要多少列,并有以下问题:列的数量(及其类型)将如何影响count(*)查询的性能。我最初的想法是,一个列更多的表将分布在更多的磁盘块上。因此,系统将不得不进行更多的磁盘查找,从而导致更长的查询。

在我研究Netezza的时候,我也欢迎与其他系统(MySql、Postgres、Vertica等)相关的答案,以帮助我的总体理解。

已经就列计数对查询性能的影响进行了多次讨论(Q1Q2Q3)。这些问题讨论的是一个通用查询,而不是没有索引的完整表扫描。因此,另一个问题是。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-10-24 20:47:39

是的,列数会间接地影响性能。列中的数据也会影响速度。

为什么会这样呢?

每个DBMS都将行存储在块中--通常是8k块,但不一定。特别是数据仓库系统倾向于使用更大的块大小。如果一个表有许多列,其中包含大量数据(请考虑varchar列),这意味着在较少的行上适合于单个数据库块。

对于支持适当隔离的事务性系统,count(*)查询必须查询表中的所有行(如果当前对事务可见,则检查每一行)。DBMS从硬盘读取的最小单元是块。因此,一个块上的行越多,所需完成的I/O就越少。

如果一个行平均花费100个字节,那么单个块将包含大约80行。要计算80行表中的所有行,数据库只需执行一次I/O操作(实际上,查找表本身要稍微多一点)。

现在,如果每行需要1000个字节,那么单个块大约包含8行,这意味着计算DB需要执行8次I/O操作的所有行。

即使数据被缓存,它仍然是一个“逻辑”I/O与8“逻辑”I/O操作。

只有在不涉及索引的情况下,上述情况才成立。

支持详细执行计划的任何DBMS都可以观察到这种效果。下面是Postgres的示例脚本:

代码语言:javascript
运行
复制
create table data5 (c1 text, c2 text, c3 text, c4 text, c5 text);
insert into data5 
select rpad('X',50,'X'),
       rpad('X',50,'X'),
       rpad('X',50,'X'),
       rpad('X',50,'X')
from generate_series(1,100000);

create table data10 (c1 text, c2 text, c3 text, c4 text, c5 text, c6 text, c7 text, c8 text, c9 text, c10 text);
insert into data10 
select rpad('X',50,'X'),
       rpad('X',50,'X'),
       rpad('X',50,'X'),
       rpad('X',50,'X'),
       rpad('X',50,'X'),
       rpad('X',50,'X'),
       rpad('X',50,'X'),
       rpad('X',50,'X'),
       rpad('X',50,'X'),
       rpad('X',50,'X')
from generate_series(1,100000);

上面创建了两个表,每个表有100.000行。一个有5列,另一个有10列。

在进行解释分析时,将返回以下内容(Postgres 9.3):

代码语言:javascript
运行
复制
explain (analyze, buffers, verbose)
select count(*)
from data5;

Aggregate  (cost=4192.00..4192.01 rows=1 width=0) (actual time=27.539..27.539 rows=1 loops=1)
  Output: count(*)
  Buffers: shared hit=2942
  ->  Seq Scan on stuff.data5  (cost=0.00..3942.00 rows=100000 width=0) (actual time=0.005..16.158 rows=100000 loops=1)
        Output: c1, c2, c3, c4, c5
        Buffers: shared hit=2942
Total runtime: 27.595 ms

Buffers: shared hit=2942行告诉我们,Postgres必须查看2942个块才能读取整个表。

下面是包含10列的表:

代码语言:javascript
运行
复制
explain (analyze, buffers, verbose)
select count(*)
from data10;

Aggregate  (cost=7917.00..7917.01 rows=1 width=0) (actual time=34.964..34.965 rows=1 loops=1)
  Output: count(*)
  Buffers: shared hit=6667
  ->  Seq Scan on stuff.data10  (cost=0.00..7667.00 rows=100000 width=0) (actual time=0.010..22.187 rows=100000 loops=1)
        Output: c1, c2, c3, c4, c5, c6, c7, c8, c9, c10
        Buffers: shared hit=6667
Total runtime: 35.025 ms

我们可以看到Postgres必须看6667个街区才能得到计数。

使用Oracle的SQL*Plus和set autotrace statistics选项可以观察到类似的情况,该选项还将显示所执行的(逻辑) I/O的数量。

data5表的统计数据如下所示:

代码语言:javascript
运行
复制
VALUE | STATISTIC                             
------+---------------------------------------
  140 | bytes received via SQL*Net from client
  755 | bytes sent via SQL*Net to client      
 2977 | consistent gets                       
    0 | db block gets                         
    0 | physical reads                        
    0 | recursive calls                       
    0 | redo size                             
 2977 | session logical reads                 
    1 | sorts (memory)                        
    2 | SQL*Net roundtrips to/from client     
    1 | rows processed                        

“一致获取”表示逻辑I/O的数量:

对于data10表,输出如下:

代码语言:javascript
运行
复制
VALUE | STATISTIC                             
------+---------------------------------------
  141 | bytes received via SQL*Net from client
  615 | bytes sent via SQL*Net to client      
 7184 | consistent gets                       
    0 | db block gets                         
    0 | physical reads                        
    0 | recursive calls                       
    0 | redo size                             
 7184 | session logical reads                 
    1 | sorts (memory)                        
    2 | SQL*Net roundtrips to/from client     
    1 | rows processed                        

我们再次清楚地看到(逻辑) I/O的增加。

票数 21
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26555797

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档