Cluster table 与性能
用户数据行存储在文件系统中的堆文件中,而这些行以不确定的顺序存储。如果表最初以插入/复制的顺序加载,那么以后的插入、更新和删除将导致在堆文件中以不可预测的顺序添加行。创建索引创建一个指向堆行的辅助文件,并将索引条目与创建索引命令中指定的列中的值进行排序。通过在索引中快速查找所需的值,可以快速找到匹配的堆行。对于大多数情况,创建索引就满足对性能的需求。但是有些情况,索引的有序与堆表的无序,会导致性能问题。这就是cluster有用的地方,它对堆进行排序,以匹配其中一个索引的排序。(非btree索引不能被聚簇,因为它们缺乏线性排序。)
Cluster 表类似于 Oracle 的索引组织表,表内容的组织顺序与特定的索引顺序一致。Cluster 指示KingbaseES基于index_name 所指定的索引来聚簇指定的表,该索引必须已经定义在 table上。当一个表被聚簇时,会基于索引信息对它进行物理上的排序。
聚簇是一种一次性的操作:当表后续被更新时,更改没有被聚簇。也就是说,不会尝试根据新行或者被更新行的索引顺序来存储它们(如果想这样做,可以周期性地通过发出该命令重新聚簇。还有,把表的 fillfactor存储参数设置为小于 100% 有助于在更新期间保持聚簇顺序,因为如果空间足够会把被更新行保留在同一个页面中)。
形式 CLUSTER table_name 会使用前面所用的同一个索引对表重新聚簇。你也可以使用 CLUSTER或者ALTER TABLE 的SET WITHOUT CLUSTER形式把索引设置为可用于未来的聚簇操作,或者清除任何之前的设置。不带任何参数的CLUSTER会重新聚簇调用用户所拥有的当前数据库中已经被聚簇过的表(如果是超级用户调用,则是所有已被聚簇过的表)。这种形式的 CLUSTER不能在一个事务块内执行。当一个表被聚簇时,会在其上要求一个ACCESS EXCLUSIVE 锁。这会阻止任何其他数据库操作(包括读和写) 在CLUSTER结束前在该表上操作。
堆表排序是如何提高性能?如果您只寻找一行,那么它在表文件中的位置并不重要。但是,假设基于索引列,检索连续的1000行,那么,我们可以快速找到1000个匹配的索引条目,那么那1000行数据呢?如果它们分散在1000个8kB的页上,则需要许多I/O访问。如果这些行都在相邻的页面上,这将减少所需的页面的数量。如果这些堆页面都在内存中,这可能并不重要,但如果有些堆页面在存储中,减少堆访问的数量可以产生显著的性能好处。
堆表排序什么时候有助于提高性能?设想以下三种情况:对于这些工作负载,对堆表的页进行排序可以大大减少I/O访问的次数。
- 索引列单个值,具有大量数据,例如,检索colname=5返回大量数据
- 访问索引列的范围值,例如,colname>=10 and colname<20
- 读取经常访问的值,例如未结算订单
使用cluster有两个缺点:
- 当 cluster 命令创建一个新的堆文件以匹配索引时,会禁止其他会话同时读取或写入该表。
- 与索引组织表不同,堆表不会保持cluster状态——其后的插入和更新操作会将行以非顺序的放置在堆中,导致堆表变得不那么有序——将需要稍后的cluster操作来恢复理想的排序。然而,cluster 确实会记住以前的cluster 操作,并且可以按照预设,自动恢复所有曾经cluster的表。
在下面的示例中,行由于它们的插入顺序而自动排序,并且对pg_stats 的查询验证相关性为1:
-- 准备数据表
CREATE TABLE public.cluster_test (col1 INTEGER, col2 TEXT);
CREATE INDEX i_cluster_test ON cluster_test (col1 );
INSERT INTO public.cluster_test SELECT *, repeat('col1', 250) FROM generate_series(1, 100000); -- 计算相关统计数据
ANALYZE cluster_test; -- 查看视图 pg_stats,correlation物理行顺序和列值逻辑顺序之间的统计关联。其范围从-1到+1。当值接近-1或+1时,在列上的一个索引扫描被认为比值接近0时的代价更低,因为这种情况减少了对磁盘的随机访问
SELECT correlation FROM pg_stats WHERE schemaname = 'public' AND tablename = 'cluster_test' AND attname = 'col1';
correlation
-------------
1
查看执行计划:
EXPLAIN (analyze,buffers) SELECT * FROM cluster_test WHERE col1 < 74000; QUERY PLAN
--------------------------------------------------------------------------------------------
Index Scan using i_cluster_test on cluster_test (cost=0.29..4863.41 rows=74064 width=258) (actual time=0.022..9.850 rows=73999 loops=1)
Index Cond: (x < 74000)
Buffers: shared hit=2945
Planning Time: 0.067 ms
Execution Time: 11.931 ms
(5 行记录) EXPLAIN SELECT * FROM cluster_test WHERE col1 < 75000;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------
Seq Scan on cluster_test (cost=0.00..4954.00 rows=75038 width=258) (actual time=0.011..10.739 rows=74999 loops=1)
Filter: (x < 75000)
Rows Removed by Filter: 25001
Buffers: shared hit=3704
Planning Time: 0.071 ms
Execution Time: 12.852 ms
(6 行记录)
您可以看到优化器在 74k 和 75k 行访问之间从索引扫描切换到顺序扫描。
下一个示例以随机顺序插入行,这会产生接近于零的相关性,以及停止使用索引的较低值,即 31k 与 75k:
--准备数据
DELETE FROM public.cluster_test;
INSERT INTO public.cluster_test SELECT *, repeat('col1', 250) FROM generate_series(1, 100000) ORDER BY random(); ANALYZE cluster_test; SELECT correlation FROM pg_stats WHERE schemaname = 'public' AND tablename = 'cluster_test' AND attname = 'col1'; correlation
---------------
0.0016185313
查看执行计划:
EXPLAIN SELECT * FROM cluster_test WHERE col1 < 10; QUERY PLAN
--------------------------------------------------------------------------------------
Index Scan using i_cluster_test on cluster_test (cost=0.42..40.57 rows=9 width=1008) (actual time=0.005..0.022 rows=9 loops=1)
Index Cond: (col1 < 10)
Buffers: shared hit=12
Planning Time: 0.093 ms
Execution Time: 0.036 ms (5 行记录) EXPLAIN SELECT * FROM cluster_test WHERE col1 < 15;
QUERY PLAN
-----------------------------------------------------------------------------
Bitmap Heap Scan on cluster_test (cost=4.53..59.94 rows=14 width=1008) (actual time=0.011..0.035 rows=14 loops=1)
Recheck Cond: (col1 < 15)
Heap Blocks: exact=14
Buffers: shared hit=17
-> Bitmap Index Scan on i_cluster_test (cost=0.00..4.52 rows=14 width=0) (actual time=0.006..0.006 rows=14 loops=1)
Index Cond: (col1 < 15)
Buffers: shared hit=3
Planning Time: 0.140 ms
Execution Time: 0.060 ms EXPLAIN SELECT * FROM cluster_test WHERE col1 < 31000;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on cluster_test (cost=1595.40..43203.42 rows=30836 width=1008) (actual time=4.229..15.893 rows=30999 loops=1)
Recheck Cond: (col1 < 31000)
Heap Blocks: exact=13206
Buffers: shared hit=13547
-> Bitmap Index Scan on i_cluster_test (cost=0.00..1587.69 rows=30836 width=0) (actual time=2.837..2.837 rows=30999 loops=1)
Index Cond: (col1 < 31000)
Buffers: shared hit=341
Planning Time: 0.071 ms
Execution Time: 16.786 ms EXPLAIN SELECT * FROM cluster_test WHERE col1 < 32000;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Seq Scan on cluster_test (cost=0.00..44108.00 rows=31893 width=1008) (actual time=9.072..25.702 rows=31999 loops=1)
Filter: (col1 < 32000)
Rows Removed by Filter: 68001
Buffers: shared hit=42858
Planning Time: 0.076 ms
Execution Time: 26.683 ms
(6 行记录)
请注意,它在10行之后从索引扫描切换到位图堆扫描,因为统计数据表明匹配的行随机存储在堆中。当使用堆排序与索引排序非常匹配的索引时,与索引扫描相比,使用位图堆扫描没有任何价值。您可以看到优化器在 31k 和 32k 行访问之间从索引扫描切换到顺序扫描,比堆表有序时,更早的切换和更长的用时。
使用cluster,我们可以强制堆匹配索引排序,并再次使得index scan可用于更多行:
CLUSTER cluster_test USING i_cluster_test;
ANALYZE cluster_test; SELECT correlation FROM pg_stats WHERE schemaname = 'public' AND tablename = 'cluster_test' AND attname = 'col1';
correlation
-------------
1
查看执行计划:
EXPLAIN SELECT * FROM cluster_test WHERE col1 < 74000;
QUERY PLAN
--------------------------------------------------------------------------------------------
Index Scan using i_cluster_test on cluster_test (cost=0.29..4836.03 rows=73642 width=258)
Index Cond: (col1 < 74000) EXPLAIN SELECT * FROM cluster_test WHERE col1 < 75000;
QUERY PLAN
---------------------------------------------------------------------
Seq Scan on cluster_test (cost=0.00..4954.00 rows=74696 width=258)
Filter: (col1 < 75000)
连续时间的数据,不需要cluster table,通常近期的数据是最常访问的。如果表几乎没有更新和删除,新行会追加到文件的末尾,自然有良好的相关排序,可以最佳的被读取处理。但是,如果有很多更新/删除,插入和更新的行被放置在表中任何free空间中,因此连续性会很低。如果对执行过了cluster的表,进行大量更新/删除,并且只访问最近的数据,这样可能会得到一个不准确的高相关值和低效的计划,因为虽然大多数行都被cluster了,而新增的行是最经常访问的,没有匹配索引加以排序。
表分区可以被认为是一种粗略的聚簇,它可以通过使用基于时间的分区来改善数据局部性来帮助处理这些工作负载。
当然,这是我对cluster table的一些思考,希望这点认知能为大家提供了一些有关何时使用聚簇表的提示。
Cluster table 与性能的更多相关文章
- 聚簇(Cluster)和聚簇表(Cluster Table)
聚簇(Cluster)和聚簇表(Cluster Table) 时间:2010-03-13 23:12来源:OralanDBA.CN 作者:AlanSawyer 点击:157次 1.创建聚簇 icmad ...
- Oracle 如何提交手册Cluster Table事务
环境遇到ora-00600 4000错误,该目的是参与cluster table,什么我这里有以下简单的模拟.以供参考! ++++创建一个测试表 ? 1 2 3 4 5 6 7 8 9 10 11 1 ...
- [20181226]简单探究cluster table.txt
[20181226]简单探究cluster table.txt --//简单探究cluster table.以前也做过,有点生疏了. 1.环境:SCOTT@book> @ ver1PORT_ST ...
- Cluster Table
对簇表来说,总是要先创建簇段(cluster segment).然后将表关联到cluster segment里.由此可知,簇表也是虚拟表,没有对应的segment,簇表对应的是cluster segm ...
- PLSQL_性能优化系列05_Oracle Hint提示
2014-06-20 Created By BaoXinjian
- 简述Oracle IOT(Index Organized Table)
转:http://blog.itpub.net/17203031/viewspace-744477 对关系型数据库产品(RDBMS)而言,一个重要特性就是:数据信息都被组织为二维数据表,信息的表达可以 ...
- MySQL 高级性能优化架构 千万级高并发交易一致性系统基础
一.MySQL体系架构 由图,可以看出MySQL最上层是连接组件.下面服务器是由连接池.管理服务和工具组件.SQL接口.查询解析器.查询优化器.缓存.存储引擎.文件系统组成. 1.连接池 管理.缓冲用 ...
- Oracle索引梳理系列(五)- Oracle索引种类之表簇索引(cluster index)
版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...
- OPTIMIZE TABLE 小解
首先看一下语法: OPTIMIZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE tbl_name [, tbl_name] ... 我们知道mysql存储引擎里面的数据和索 ...
随机推荐
- iNeuOS工业互联网操作系统,视图建模(WEB组态)增加2154个行业矢量图元、大屏背景及相关图元
1. 概述 现在三维数字孪生(3D)比较流行,各行业各领域的项目也都在上数字孪生项目或是项目中包括数字孪生模块,能做的厂家也很多.从全厂区的应用视觉的冲击力还是比较震撼,但是数字孪生不太可能包括 ...
- 简单实现python接口自动化(一)
目的:excel中维护接口用例数据,通过python中requests库进行读取用例,并把运行结果与excel中的预期结果对比,最后把执行情况写入到excel中去. excel维护数据: 具体的接口名 ...
- 排名前三——python 开源 IDE
写在前面的一些P话: Python无处不在 ,似乎它支持从主要网站到桌面实用程序到企业软件的所有功能. Python已经被用来编写流行的软件项目,如dnf / yum,OpenStack,OpenSh ...
- 腾讯云数据库公有云市场稳居TOP 2!
7月4日,国际权威机构IDC发布的<2021年下半年中国关系型数据库软件市场跟踪报告>显示,腾讯云数据库在关系型数据库软件市场(公有云模式)中,位列第二. IDC报告显示,2021下半年中 ...
- C#请求HTTPS地址的故障分析和TLS知识点总结
背景介绍 近期收到同事反馈,在C#程序中通过HTTPClient请求一个HTTPS的地址时,在本地开发环境和测试环境均能正常执行,而部署到生产环境后发生异常且稳定复现,异常提示为:[请求被中止: 未能 ...
- 什么新东西值得学「GitHub 热点速览 v.22.29」
上周 18k+ 的项目 bun 这周又获得 7k+ star,是时候了解下它背后的编程语言 zig 了,它并不是一门新的语言,伴随着 bun 的风靡,zig 本周也上了 GitHub 热榜.同样,可以 ...
- GIS技术在医疗行业的应用:利用切片地图发布技术解决dmetrix数字病理切片在线浏览
最近一直在研究切片地图发布技术,解决各种矢量和栅格数据的切片地图制作和发布问题.这块的技术在土地评估和调查类公司中应用较多,因为他们经常需要使用各地地图,传统的文件管理方式很难适应工作现状,如果将各种 ...
- BootStrapBlazor 安装教程--Server模式
使用模板 使用模板是最简单的办法.因为项目模板里已经包含了BootStrapBlazor的所有需要配置的内容. 首先我们安装项目模板: dotnet new -i Bootstrap.Blazor.T ...
- 第十一天python3 递归函数
递归Recursion 函数直接或者间接调用自身就是递归: 递归需要有边界条件,递归前进段.递归返回段: 递归一定要有边界条件: 当边界条件不满足的时候,递归前进: 当边界条件满足的时候,递归返回: ...
- 【MySQL 8】Generated Invisible Primary Keys(GIPK)
从MySQL 8.0.30开始,MySQL支持在GIPK模式下运行时生成不可见的主键.在这种模式下运行时,对于任何在没有显式主键的情况下创建的InnoDB表,MySQL服务器会自动将生成的不可见主键 ...