我无法获得将常规表连接到分区视图以消除不符合分区列谓词的表的查询。特别是,我对我对分区视图进行 LEFT OUTER JOIN 并且我的谓词涵盖一系列值的情况感兴趣。当我修改查询以使用 INNER JOIN 或将谓词限制为单个值时,表被正确消除。这是一个演示该问题的脚本。我在 SQL Server 2016 SP1 中对此进行了测试。
--Create 2 tables for prices; 1 for 2017 and 1 for 2018
CREATE TABLE Price_2017
(
PriceDate DATE NOT NULL,
PriceValue FLOAT NOT NULL
)
GO
ALTER TABLE Price_2017 ADD CONSTRAINT PK_Price_2017 PRIMARY KEY(PriceDate);
GO
ALTER TABLE Price_2017 WITH CHECK ADD CONSTRAINT CK_Price_2017
CHECK (PriceDate >= '2017-01-01' AND PriceDate <= '2017-12-31');
GO
ALTER TABLE Price_2017 CHECK CONSTRAINT CK_Price_2017;
GO
CREATE TABLE Price_2018
(
PriceDate DATE NOT NULL, …Run Code Online (Sandbox Code Playgroud) 我有一个用于存储事件的表,该表timestamptz使用按月按列分区PARTITION BY RANGE。
目前有 5 个分区,每个分区包含一个月的跨度,从 开始FOR VALUES FROM ('2018-01-01') TO ('2018-02-01')到结束FOR VALUES FROM ('2018-05-01') TO ('2018-06-01')。
大多数数据都是以线性且可预测的方式输入的。但是,事件由报告事件的应用程序消耗,并且我确实必须允许随时输入过去的事件 - 其时间戳可能早于2018-01-01,甚至是未来的事件(例如预计的费用)发生在未来的某个时间)。
我计划为过去的事件创建一个分区,这些事件的跨度将超过一个月,因为预计不会有太多此类事件。
我不确定对于尚未存在分区的未来事件的最佳方法是什么。
有没有办法获取我可以在现有分区中存储的最小/最大值?如果没有,我可以创建一个参考表来存储这些值,但我宁愿不必维护它。
我应该创建一个触发器来检查插入的每一行(看起来很昂贵)吗?我应该捕获插入错误并一次处理这些错误吗?
运行于PostgreSQL 10.3.
我正在尝试将以下连接查询作为 MariaDB 10.1.26 上更复杂查询的一部分运行。
select distinct
project_commits.project_id,
date_format(created_at, '%x%v1') as week_commit
from project_commits
left join commits
on project_commits.commit_id = commits.id;
Run Code Online (Sandbox Code Playgroud)
两个连接字段都被索引。但是,连接涉及对 的完整扫描project_commits和索引查找commits。的输出证实了这一点EXPLAIN。
+------+-------------+-----------------+--------+---------------+---------+---------+-------------------------------------+------------+-----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-----------------+--------+---------------+---------+---------+-------------------------------------+------------+-----------------+
| 1 | SIMPLE | project_commits | ALL | NULL | NULL | NULL | NULL | 5417294109 | Using temporary |
| 1 | SIMPLE | commits | …Run Code Online (Sandbox Code Playgroud) 我有下表。
我也想加分区。
CREATE TABLE `app_log_Test` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`dateCreated` datetime NOT NULL,
`host` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`label` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`event` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`level` varchar(8) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`message` text COLLATE utf8mb4_unicode_ci,
`version` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `app_log_dateCreated` (`dateCreated`),
KEY `app_log_label` (`label`),
KEY `app_log_event` (`event`),
KEY `app_log_level` (`level`)
) ENGINE=TokuDB `COMPRESSION`=tokudb_quicklz
Run Code Online (Sandbox Code Playgroud)
我正在使用 MariaDB 10。
MariaDB [test2]> alter table app_log_Test partition by RANGE(TO_DAYS(dateCreated))(
-> PARTITION …Run Code Online (Sandbox Code Playgroud) 我们有一个表结构,父记录和子记录位于同一个表中。它们通过列 ( parentId ) 引用,该列引用父记录(顶部父记录上为 null)。此外,我们有一个请求的日期列,我们通过该列进行所有查询,但唯一具有此值的记录是父记录。
由于我们所有的查询最初都是根据父结果进行过滤并使用此日期,因此我们希望在此日期范围内对表进行分区,但我们知道这是不可能的,因为子记录的记录中存在空值。
除了在数据库中的每个子记录上创建一个“虚拟”值(一些永远不会在我们的过滤器中捕获的任意日期)之外,我们还有什么其他选择?是否不可能以某种方式为我们从未查询过的所有空值创建一个单独的分区?
我们每个月都尝试过以下方法。
表大小约为 2TB,3000 万行,包含 50 列,因此我们开始重命名旧表并将新表分区为一批 10K 行。对于 1000 万行,大约需要 7 个小时。
我们正在寻找可以在最短停机时间内完成的任何快速有效的方法?任何帮助表示赞赏。
我有以下分区表
create table T (Month char(6), ID int, .... primary key (ID, Month)) on psMonth(Month)
Run Code Online (Sandbox Code Playgroud)
分区函数是
CREATE PARTITION FUNCTION [pfMonth](char(6)) AS
RANGE RIGHT FOR VALUES (N'200001', .... N'200705', N'200706', N'200707', ....)
Run Code Online (Sandbox Code Playgroud)
但是,以下查询显示的实际分区数是 260 而不是 1?
select count(*)
from T (nolock)
where Month = '200706'
Run Code Online (Sandbox Code Playgroud)
执行计划是
|--计算标量(DEFINE:([Expr1004]=CONVERT_IMPLICIT(int,[globalagg1006],0)))
|--Stream Aggregate(DEFINE:([globalagg1006]=SUM([partialagg1005])))
|--Parallelism(Gather Streams)
|--Stream Aggregate(DEFINE:([partialagg1005]=Count(*)))
|--聚簇索引扫描(OBJECT:([DB].[dbo].[T].[PK_T]), WHERE:([DB].[dbo].[T].[Month]=[@1] ))
更新:如果我运行以下查询
,查询运行速度很快,实际分区计数为 1。
select count(*), $partition.pfMonth(Month)
from T with (nolock)
where Month = '200706'
group by $partition.pfMonth(Month)
Run Code Online (Sandbox Code Playgroud)
更新 2:
以下查询也只扫描一个分区。 …
我知道一些知识:
分区用来实现更好的性能(如在描述该文章)
和索引用于提高选择操作的性能。
结果我的问题是:在哪些情况下我应该使用索引,在哪些情况下我应该使用分区表。
换句话说,在不同的操作(选择、删除、更新)索引或表分区中什么应该更好,以及为什么。
谢谢。
我需要将 LONG 数据类型的 high_value 与 DATE 数据类型的 sysdate 进行比较。我需要获取 90 天前的所有分区的分区名称。代码是这样的。
declare
dt date;
time_to_stay number:=1; --CONFIGURE AS PER THE REQUIREMENT
begin
for x in (select partition_name , high_value, partition_position
from user_tab_partitions
where table_name = 'DEMO')
loop
execute immediate 'select '||x.high_value||' from dual' into dt;
if to_date(dt) < sysdate-time_to_stay AND x.partition_position <>'1' then
execute immediate 'ALTER TABLE DEMO DROP PARTITION '|| x.partition_name|| ' UPDATE GLOBAL INDEXES';
Run Code Online (Sandbox Code Playgroud)
此查询会执行但不会删除分区。但是我看到主要问题是将 high_value 的 LONG 数据类型转换为 DATE 以在 high_value 和 sys_date 之间进行比较。
我怎样才能解决这个问题?
我需要拆分一个 Oracle 分区,我对执行拆分时 Oracle 是否要物理重新定位数据感到困惑。这是我打算做的:
alter table SCHEMA.DATATABLE
split partition MAXVAL_PART
at (TO_DATE(' 2013-04-01 00:00:00',
'SYYYY-MM-DD HH24:MI:SS',
'NLS_CALENDAR=GREGORIAN'))
into (partition PARTFOREXISTINGROWS
tablespace EXISTINGMAXVALTABLESPACE,
partition MAXVAL_PART
tablespace NEWMAXVALTABLESPACE);
Run Code Online (Sandbox Code Playgroud)
问题是我当前的 MAXVAL_PART 中有 320 GB 的数据,我不想在磁盘上物理移动这些数据。如果我在 2013 年 4 月 1 日切断分区,那么新分区中将没有数据,但是我收到了关于这是否仍然需要移动所有数据的相互矛盾的信息。理想情况下,Oracle 看到我的新 MAXVAL 分区将为空,在新表空间中定义它,然后我就完成了。
此命令会移动磁盘上已有的数据,还是将其留在原处并创建一个新分区?
这篇文章说 Oracle 会检测空分区并进行快速拆分 http://docs.oracle.com/cd/B19306_01/server.102/b14231/partiti.htm
但是我在很多地方看到拆分意味着所有数据都被移动到新的存储中。是哪个?
partitioning ×10
sql-server ×4
mariadb ×2
mysql ×2
oracle ×2
postgresql ×2
index ×1
join ×1
null ×1
performance ×1
plpgsql ×1
tokudb ×1