我使用SQL Server 2008 R2并知道Indexed View不能有自我加入。
我有一个树表有ID和ParentID列,我需要在这个表上创建索引视图自每个记录与父记录之间的连接。我可以在这个视图中模拟自连接吗?
编辑
我的表结构是:
SAM.Detail (DetailID Int, ParentDetailID Int, Quantity Int, ...)
Run Code Online (Sandbox Code Playgroud)
我的查询是:
Select A.DetailID,
A.Quantity - SUM(B.Quantity) as RemainQuantity,
COUNT_BIG(*) as CountBig
From SAM.Detail A
inner join SAM.Detail B ON B.ParentDetailID = A.DetailID
Group By A.DetailID, A.Quantity
Run Code Online (Sandbox Code Playgroud) sql-server-2008 sql-server sql-server-2008-r2 view materialized-view
假设我有一个由以下 SQL 定义的视图:
SELECT t1.id, t2.name, t3.address
FROM Table1 as t1
INNER JOIN Table2 t2
ON t1.id = t2.tID
INNER JOIN Table3 t3
ON t1.id = t3.tID
Run Code Online (Sandbox Code Playgroud)
据我所知,如果我在这个视图上创建一个索引,那么数据将被持久化,但我不清楚究竟是什么被持久化了。假设我在 t1.id 上创建了一个唯一的聚集索引,是否将所有三列都保存到磁盘中,或者是否仍会在运行时计算从 table2 和 table3 中提取的值?
如果其中任何一个没有意义,或者我是否遗漏了任何重要内容,请告诉我。
假设我有父-> 子表设置。打电话给他们Shipment和Widget。
无论如何要创建一个索引视图,该视图将具有父级 (ShipmentId) 的 PK 和最新子级 (Widget.CreatedWhen) 的创建时间。
这是我正在寻找的查询:
SELECT widg.ShipmentId, MAX(widg.CreatedWhen) NewestWidget
FROM dbo.Widget widg
GROUP BY widg.ShipmentId
Run Code Online (Sandbox Code Playgroud)
显然这个查询不能是一个索引视图,因为它已经MAX在里面了。
但是是否有其他方法通过“索引视图合法”SQL 来获得类似的结果集?
I'd like to create a simple materialized view from a table which lies in a different database. The two databases are on the same server.
What do I have to add to make the query access the foreign database and the table there?
CREATE MATERIALIZED VIEW mv_table_1 AS
SELECT *
FROM public.mv_table_1 --The schema & table from the different DB
WITH DATA;
Run Code Online (Sandbox Code Playgroud)
I tried using the fully qualified table name (db name before the schema name) but this results in …
我有以下版本的 SQL Server:
Microsoft SQL Server 2014 (SP3) (KB4022619) - Windows NT 6.3 上的 12.0.6024.0 (X64) 企业版(64 位)(内部版本 9600:)(管理程序)
我创建了以下视图
CREATE VIEW [dbo].[vwGroupsOfficesDependencies]
WITH SCHEMABINDING
AS
SELECT GC.IdGroup, COUNT_BIG(*) AS countBig, OD.IdOffice
FROM dbo.Group AS GC INNER JOIN
dbo.GroupDependencies AS GD ON GC.IdGroup = GD.IdGroup INNER JOIN
dbo.OfficeDependencies AS OD ON OD.IdDependency = GD.IdDependency INNER JOIN
dbo.Dependencies AS D ON D.IdDependency = GD.IdDependency
WHERE (D.Active = 1)
GROUP BY GC.IdGroup, OD.IdOffice
Run Code Online (Sandbox Code Playgroud)
然后我创建了聚集索引
CREATE UNIQUE CLUSTERED INDEX [IX_vwGroupsOfficesDependencies_IdOficeIdGroup] ON [dbo].[vwGroupsOfficesDependencies]
( …Run Code Online (Sandbox Code Playgroud) sql-server optimization hints materialized-view sql-server-2014
我有一个索引视图的适度用例,它折叠一列并总结一个大表中的所有条目:
CREATE VIEW dbo.Losses_CombinedPortfolio WITH SCHEMABINDING
AS
SELECT [Category], [Year],
SUM(ISNULL(Loss,0)) AS [Loss], COUNT_BIG(*) as [Count]
FROM dbo.Sub_Portfolio_Losses
GROUP BY [Category], [Year]
GO
CREATE UNIQUE CLUSTERED INDEX Idx
ON dbo.Losses_CombinedPortfolio([Category], [Year]);
Run Code Online (Sandbox Code Playgroud)
我最初的目标更加雄心勃勃,但索引视图的限制如此之多......我很高兴能够让它发挥作用。
可悲的是,当我尝试对此索引视图进行基本查询时:
SELECT TOP (100) *
FROM Losses_CombinedPortfolio
ORDER BY Loss DESC
Run Code Online (Sandbox Code Playgroud)
...查询也很慢,实际执行计划表明它总是回到源表并每次从头开始计算聚合:
我只能假设这是因为我计算出的“损失”列没有被具体化 - 但这会让我感到惊讶,因为聚集索引创建成功。
请注意,此视图的主要用例是按Loss降序排序,但我无法明确创建包含它的索引:
CREATE UNIQUE CLUSTERED INDEX Idx
ON dbo.Losses_CombinedPortfolio
(Category, Loss DESC, [Year]);
Run Code Online (Sandbox Code Playgroud)
我收到错误:
无法在视图 'dbo.Losses_CombinedPortfolio' 上创建索引或统计信息 'Idx',因为关键列 'Loss' 是不精确的、已计算的且未持久化。考虑删除对视图索引或统计键中的列的引用或更改列以使其精确。如果在基表中计算列,请考虑在那里将其标记为 PERSISTED。
我尝试通过将总损失转换为除float(甚至尝试将其截断为bigint)以外的类型来解决“不精确”,但似乎此错误源于用于计算总和的基础类型。
我很困惑 - 我看到其他问题声称他们能够成功地执行聚合,例如sum …
我在我们当前的项目中多次遇到这里描述的问题,我想了解它是如何发生的以及如何在将来防止它。
DBA_SUMMARIES在那里为用户的 MV 创建条目的含义和原因是什么?主要问题是SYSDBA删除冲突摘要需要特权。由于我们SYSDBA在目标实例上没有帐户,因此我们无法在没有数据库支持团队人员介入的情况下重新创建我们的 MV。
任何指向文档的指针,如果有人可以解释背后的逻辑DBA_SUMMARIES是什么以及我如何防止这个问题发生,那就太好了。
我们观察到的 Oracle 版本是 11.2.0.1.0(在 64 位 Linux 上),我们没有支持合同,因此无法获得 Oracle 支持。
更新/解决方案
感谢下面杰克的回答,我已经能够绕过这个问题,因为我们似乎真的遇到了他提到的错误。当我第一次删除 MV 上的所有索引时,我没有收到错误消息,并且能够按预期重新创建 MV(它在USER_OBJECTS删除后不再显示)。
这就是我现在的做法(为简洁起见剪掉了):
SET serveroutput ON
SET echo ON
DECLARE
CURSOR mv_indexes
IS
SELECT 'DROP INDEX '
|| index_name AS stmt
FROM user_indexes
WHERE table_name = 'MV_NAME'
AND table_owner = 'USER';
BEGIN
FOR ix IN mv_indexes
LOOP
dbms_output.put_line('Executing: ' || ix.stmt);
EXECUTE immediate ix.stmt;
END LOOP; …Run Code Online (Sandbox Code Playgroud) 是否有可能在 PostgreSQL 中内置物化视图?
我不想要 Gardner 版本或类似由触发器填充的物理表之类的东西。我读过正在/正在部署的东西......
首先,抱歉标题太长。
我将示例减少到最少,以使其更清晰,因此不再有有意义的语义。
DBMS:Azure SQL 数据库 V12。
假设有下表:
CREATE TABLE [dbo].[MuchDataTable](
[SmallDateTimeColumn] [smalldatetime] NOT NULL
)
GO
CREATE CLUSTERED INDEX [IX_MuchDataTable_SmallDateTimeColumn] ON [MuchDataTable] ([SmallDateTimeColumn])
Run Code Online (Sandbox Code Playgroud)
现在我想获取特定于任意天数范围的聚合数据。由于该表包含很多行(超过 150 Mio。)我创建了一个索引视图,它基本上如下所示:
CREATE VIEW [dbo].[AggregatedDateView]
WITH SCHEMABINDING
AS
SELECT CONVERT(DATE, [SmallDateTimeColumn]) AS [DateColumn], COUNT_BIG(*) AS [Count]
FROM [dbo].[MuchDataTable]
GROUP BY CONVERT(DATE, [SmallDateTimeColumn])
GO
CREATE UNIQUE CLUSTERED INDEX [IX_AggregatedDateView_Date] ON [dbo].[AggregatedDateView] ([DateColumn])
Run Code Online (Sandbox Code Playgroud)
对于我的一天分组,我将每个都转换DateTime为Date. 然后我在视图上创建一个聚集索引。
对视图执行简单的 SELECT * 扫描视图的索引。没关系:
但是,如果我在计算日期列上使用 WHERE 约束进行查询,则会对原始表执行聚集索引查找:
我的理解是,应该有一个 B 树,其中包含索引视图的所有转换日期。SQL Server 为什么选择扫描底层表的聚集索引?这对索引视图是不可能的,我必须在触发器和普通表之上构建解决方案吗? …
例如,给出这样的物化视图(Postgres 10.3):
create materialized view my_view as
select * from my_table where sell_date < '2018-03-01';
Run Code Online (Sandbox Code Playgroud)
在sell_date比较值('2018-03-01')有时可以改变,但我想,以避免掉落,每次重新创建物化视图。我想出的唯一想法是使用带有一些元数据值的外部表,例如所需的日期:
create materialized view my_view as
select * from my_table where sell_date <
(select original_sell_date from some_metadata_table);
Run Code Online (Sandbox Code Playgroud)
有没有其他方法可以解决 Postgres 上物化视图的这种限制?
我当前解决方案的问题之一是您可以有两个或多个使用相同值的物化视图,但它们可能需要在某些点使用不同的值。在这种情况下,需要复制元数据表。
sql-server ×6
postgresql ×3
optimization ×2
foreign-data ×1
hints ×1
index ×1
oracle ×1
view ×1