分区表的查询

  前一篇文章提到了在2014下分区表引起的奇葩问题,最近也在苦苦研究问题的原因。这篇文章主要讲述在分区表下,查询是怎么样的一个情况。由于2014的新功能“参数估计”下是如何运转的目前无从得知,所以只能分享下2008下的原理了...

  在 SQL Server 2008 中,已分区表的内部表示形式已发生变化,即已分区表将作为一个多列索引呈现给查询处理器,其中 PartitionID是第一列。PartitionID 是一个隐藏的计算列,用于在内部表示包含特定行的分区的 ID。例如,假设一个定义为 T(a, b, c) 的表 T 在 a列进行了分区,并在 b 列的聚集索引。在 SQL Server 2008 中,此分区表在内部被视为一个具有架构 T(PartitionID, a, b, c) 的未分区表,并具有组合键 (PartitionID, b) 的聚集索引。这样查询优化器便可以基于 PartitionID 对任何已分区表或索引执行查找操作。

  此外,查询优化器的功能也得以扩展,可以针对 PartitionID(作为逻辑首列)以及其他可能的索引键列执行某一条件下的查找或扫描操作,然后,对于符合第一级查找操作的条件的每个不同值,再针对一个或多个其他列执行不同条件下的二级查找。也就是说,这种称为“skip-scan”的操作允许查询优化器基于某一条件来执行查找或扫描操作以确定要访问的分区,然后在该运算符内执行一个二级索引查找操作以返回这些分区中符合另一个不同条件的行。例如,请考虑以下查询。

  SELECT * FROM T WHERE a < 10 and b = 2;

对于本示例,假设定义为 T(a, b, c) 的表 T 对 a 列进行了分区,并具有 b 的聚集索引。表 T 的分区边界由以下分区函数定义:

  CREATE PARTITION FUNCTION myRangePF1 (int) AS RANGE LEFT FOR VALUES (3, 7, 10);

  为求解该查询,查询处理器将执行第一级查找操作以查找包含符合条件 T.a < 10 的行的每个分区。这将标识要访问的分区。然后,在所标识的每个分区内,处理器将针对 b 列的聚集索引执行一个二级查找以查找符合条件 T.b = 2 和 T.a < 10 的行。

下图所示为跳跃扫描操作的逻辑表示形式,其中显示了在 a 列和 b 列中包含数据的表 T。分区编号为 1 到 4,分区边界由垂直虚线表示。对分区执行的第一级查找操作(图中未显示)已确定分区 1、2 和 3 符合查找条件(由为该表定义的分区和 a 列的谓词指示),即T.a < 10。曲线指示了跳跃扫描操作的二级查找部分所遍历的路径。实际上,跳跃扫描操作将在这些分区的每个分区中查找符合条件 b = 2 的行。跳跃扫描操作的总开销等于三个单独索引查找之和。

-------已分区堆的执行计划------------------------------------------------------

  

  已分区堆被视为分区 ID 的逻辑索引。已分区堆的分区排除在执行计划中表示为一个 Table Scan 运算符,其中对分区 ID 使用了 SEEK 谓词。下面的示例显示了所提供的显示计划信息:

|-- Table Scan (OBJECT: ([db].[dbo].[T]), SEEK: ([PtnId1001]=[Expr1011]) ORDERED FORWARD)

------归置联接的执行计划--------------------------------------------------------

  使用相同或等效的分区函数对两个表进行分区并且在查询的联接条件中指定了来自联接两侧的分区依据列时就会发生联接归置。查询优化器可以生成一个计划,其中具有相等分区 ID 的每个表的分区将分别联接在一起。归置联接可能比非归置联接的执行速度快,因为前者可以只需较少的内存和处理时间。优化器会基于成本估计来选择非归置计划或归置计划。

在归置计划中,Nested Loops 联接从内侧读取一个或多个联接表或索引分区。Constant Scan 运算符内的数字表示分区号。

为已分区表或索引生成归置联接的并行计划时,在 Constant Scan 和 Nested Loops 联接运算符之间会出现一个 Parallelism 运算符。在此情况下,在联接外侧的多个线程会各自在不同的分区上进行读取和操作。

下图显示了一个归置联接的并行查询计划。

------并行查询执行策略--------------------------------------------------------

  查询处理器对从已分区对象选择的查询使用查询执行策略。作为执行策略的一部分,查询处理器会确定查询所需的表分区,以及要分配给每个分区的线程比例。在大多数情况下,查询处理器会为每个分区分配数量相等或几乎相等的线程,然后在这些分区中并行地执行查询。以下几段更详细地介绍了线程分配情况。

如果线程数小于分区数,则查询处理器会将每个线程分配给一个不同的分区,最初会有一个或多个分区没有获得分配的线程。当线程完成在一个分区上的执行时,查询处理器会将它分配给下一个分区,直到每个分区都分配有一个线程。这是查询处理器将线程重新分配给其他分区的唯一情况。

如果线程数与分区数相等,则查询处理器会为每个分区分配一个线程。当线程完成时,不会重新分配给另一个分区。

如果线程数大于分区数,则查询处理器会为每个分区分配相等数量的线程。如果线程数并非恰好是分区数的倍数,则查询处理器会为某些分区额外分配一个线程,以使用所有可用线程。请注意,如果只有一个分区,则会将所有线程都分配给该分区。在下图中,有四个分区和 14 个线程。每个分区都分配有 3 个线程,两个分区具有一个额外的线程,总共分配了 14 个线程。当线程完成时,不会重新分配给另一个分区。

尽管以上示例指出了一种分配线程的简单方式,但实际策略要复杂一些,并需要考虑在查询执行过程中出现的其他变化因素。例如,如果表已分区,并在 A 列上有一个聚集索引,并且查询有谓词子句 WHERE A IN (13, 17, 25),则查询处理器将为这三个查找值(A=13、A=17 和 A=25))各分配一个或多个线程,而不是为每个表分区分配一个或多个线程。只需在包含这些值的分区中执行查询,并且如果所有这些查找谓词都恰好在同一个表分区中,则所有线程都将分配给同一个表分区。

为了举出另一个示例,假定表在 A 列上有四个分区(边界点为 (10, 20, 30)),在 B 列上有一个索引,并且查询有一个谓词子句WHERE B IN (50, 100, 150)。因为表分区是基于值 A,所以值 B 可以出现在任何表分区中。这样,查询处理器将分别在四个表分区中查找三个 B 值 (50, 100, 150) 中的每一个值。查询处理器将按比例分配线程,以便它可以并行执行 12 个查询扫描中的每一个扫描。


基于 A 列的表分区


在每个表分区中查找 B 列


表分区 1:A < 10


B=50, B=100, B=150


表分区 2:A >= 10 AND A < 20


B=50, B=100, B=150


表分区 3:A >= 20 AND A < 30


B=50, B=100, B=150


表分区 4:A >= 30


B=50, B=100, B=150

时间: 2024-07-30 19:45:20

分区表的查询的相关文章

oracle分区表查询

ORACLE分区表的查询 假如 [分区表] 在字段 [createdate] 上进行分区,每个月为一个分区: 2009年6月为分区P200906 2009年7月为分区P200907 2009年8月为分区P200908 执行SQL 使用分区键检索: select*from 分区表 t where createdate > to_date('2009-07-12','yyyy-mm-dd') and createdate < to_date('2009-08-12','yyyy-mm-dd') 执

详解MySQL查询缓存

查询缓存是指存储使用SELECT语法查询到的返回到客户端的文本.当相同的请求再次发生时,会从查询缓存中获取数据,而非再执行一遍查询.查询缓存是共享Session会话的,所以一个客户端的请求可能与另一个客户端的请求得到相同的结果. 当服务器频繁收到相同的请求而数据库中的表数据变化频率又不高,查询缓存是非常有用的,它可以大大提高应用程序的访问效率.很多Web服务器利用这一原理基于数据库的内容动态生成页面. 查询缓存并不会返回过期的数据,当数据库中的表数据发生变化时,相关的查询缓存会自动清除.但是查询

分区表与分区索引

(一)什么是分区 所谓分区,就是将一张巨型表或巨型索引分成若干个独立的组成部分进行存储和管理,每一个相对小的,可独立管理的部分,称为分区. (二)分区的优势 提高数据可管理性.对表进行分区,数据的加载.索引的创建与重建.数据的备份与恢复等操作都可以在分区表上进行,而不必在表级别上进行,提高了数据的可管理性: 增强数据库的可用性.某个分区出现问题,只影响该分区,其它分区照常运作: 改善查询性能.将对整个表的查询转化为对某个分区表的查询,提高了查询速度: 提高数据库操作的并行性.可对分区表进行并行操

MySQL分区表的局限和限制

禁止构建 分区表达式不支持以下几种构建: 存储过程,存储函数,UDFS或者插件 声明变量或者用户变量 可以参考分区不支持的SQL函数 算术和逻辑运算符 分区表达式支持+,-,*算术运算,但是不支持DIV和/运算(还存在,可以查看Bug #30188, Bug #33182).但是,结果必须是整形或者NULL(线性分区键除外,想了解更多信息,可以查看分区类型). 分区表达式不支持位运算:|,&,^,<<,>>,~ . HANDLER语句 在MySQL 5.7.1之前的分区表不

【PostgreSQL】分区表

PostgreSQL中的分区表是通过表继承来实现的(表继承博客http://www.cnblogs.com/NextAction/p/7366607.html).创建分区表的步骤如下: (1)创建“父表”,所有的分区表都从这张表继承.“父表”中不存数据,也不要定义约束和索引. (2)创建“子表”,所有“子表”都是从“父表”中继承而来.这些“子表”就是所谓的分区,其实它们也是PostgreSQL表. (3)给分区表创建约束. (4)在分区表上创建索引. (5)创建触发器,把对“父表”的插入重定向到

oracle按时间创建分区表

首先明确分区表和表分区的区别:表分区是一种思想,分区表示一种技术实现.当表的大小过G的时候可以考虑进行表分区,提高查询效率,均衡IO.oracle分区表是oracle数据库提供的一种表分区的实现形式.表进行分区后,逻辑上仍然是一张表,原来的查询SQL同样生效,同时可以采用使用分区查询来优化SQL查询效率,不至于每次都扫描整个表 一.分区表基本操作 1.按时间分区表创建: create table t_test ( pk_id number(30) not null, add_date_time

MySQL分区表使用方法

原文:MySQL分区表使用方法 1. 确认MySQL服务器是否支持分区表 命令: show plugins; 2. MySQL分区表的特点 在逻辑上为一个表,在物理上存储在多个文件中 HASH分区(HASH) HASH分区的特点 根据MOD(分区键,分区数)的值把数据行存储到表的不同分区中 数据可以平均的分布在各个分区中 HASH分区的键值必须是一个INT类型的值,或是通过函数可以转为INT类型 如何建立HASH分区表 以INT类型字段 customer_id为分区键 CREATE TABLE

PostgreSQL 创建分区表(转 仅供自己参考)

典型使用场景 随着使用时间的增加,数据库中的数据量也不断增加,因此数据库查询越来越慢. 加速数据库的方法很多,如添加特定的索引,将日志目录换到单独的磁盘分区,调整数据库引擎的参数等.这些方法都能将数据库的查询性能提高到一定程度. 对于许多应用数据库来说,许多数据是历史数据并且随着时间的推移它们的重要性逐渐降低.如果能找到一个办法将这些可能不太重要的数据隐藏,数据库查询速度将会大幅提高.可以通过DELETE来达到此目的,但同时这些数据就永远不可用了. 因此,需要一个高效的把历史数据从当前查询中隐藏

Hive编程指南_学习笔记01

第四章: HQl的数据定义 1:创建数据库 create database financials; create database  if not exists financials; 2: 查看数据库 show databases; 模糊查询数据库 show databases like 'h.*' ; 3:创建数据库改动数据库的默认位置 create database financials localtion '/my/preferred/directory' 4:添加数据库的描写叙述信息