RDK*_*RDK 2 mysql database postgresql performance
我正在创建基准表来测量我们的Netezza盒子上的每小时负载(查询延迟,查询持续时间).我对表中想要的行数有了一个很好的了解,我正在尝试确定列的数量.没有索引; 我将运行全表扫描.
我正在尝试确定基准表中需要多少列,并且有以下问题:列数(及其类型)将如何影响计数(*)查询的性能.我最初的想法是,具有更多列的表将分布在更多磁盘块上.因此,系统将不得不进行更多磁盘搜索,从而导致更长的查询.
当我在Netezza工作时,我也欢迎与其他系统相关的答案(MySql,Postgres,Vertica等)以帮助我理解.
关于列数对查询性能的影响,已经有几个讨论(Q1,Q2,Q3).这些问题讨论的是通用查询,而不是没有索引的全表扫描.因此,单独的问题.
a_h*_*ame 14
是的,列数将间接影响性能.该数据在列也会影响速度.
这是为什么?
每个DBMS都以块为单位存储行 - 通常为8k块,但不一定如此.特别是数据仓库系统倾向于使用更大的块大小.如果一个表有许多列,其中包含大量数据(想想varchar列),这意味着在较少的行上适合单个数据库块.
对于支持适当的隔离事务系统count(*)查询必须查询所有表中的行(并检查每一行,如果它是目前可见的交易).DBMS从硬盘读取的最小单元是块.因此,适合块的行数越多,需要的I/O就越少.
如果行平均占用100个字节,则单个块将包含大约80行.要计算包含80行的表中的所有行,数据库只需要执行单个I/O操作(实际上,查找表本身需要多一点).
现在,如果每行需要1000个字节,则单个块包含大约8行,这反过来意味着计算DB需要执行8个I/O操作的所有行.
即使数据被缓存,它仍然是1"逻辑"I/O与8"逻辑"I/O操作.
如果不涉及索引,则上述情况也适用.
任何支持详细执行计划的DBMS都可以观察到这种影响.以Postgres为例:
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);
Run Code Online (Sandbox Code Playgroud)
上面创建了两个表,每个表有100.000行.一个有5列,另一个有10列.
在进行解释分析时,将返回以下内容(Postgres 9.3):
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
Run Code Online (Sandbox Code Playgroud)
该行Buffers: shared hit=2942告诉我们Postgres必须查看2942个块才能读完整个表格.
现在有10列的表:
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
Run Code Online (Sandbox Code Playgroud)
我们可以看到Postgres必须查看6667块才能获得计数.
使用Oracle的SQL*Plus和set autotrace statistics可以显示执行的(逻辑)I/O量的选项也可以观察到类似的事情.
data5表的统计信息如下所示:
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
Run Code Online (Sandbox Code Playgroud)
"一致获取"表示逻辑I/O的数量:
对于data10表,输出如下:
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
Run Code Online (Sandbox Code Playgroud)
我们再次清楚地看到(逻辑)I/O的增加