我在存储过程中有一个查询,它必须列出一个范围内的所有日期,并从表中加入日期(如果当天存在的话)。
这个过程是在我成为DBA之前创建的,所以我想我可以优化一下。但是,我似乎碰到了一堵砖墙,我不明白为什么。
过程的当前实现从两个普通表(我们称它们为 TableA 和 TableB)中作为派生查询(在 FROM 子句中)中选择数据,然后将其作为 RIGHT JOIN 放在上面:
RIGHT JOIN (
SELECT DATEADD(DAY,number,@DateFrom) AS DATE
FROM (
SELECT DISTINCT number
FROM master.dbo.spt_values
WHERE name IS NULL
) n
WHERE DATEADD(DAY,number,@DateFrom) <= @DateTo
) AS y ON derived.Date = y.Date -- "derived" is an alias of the derived query
Run Code Online (Sandbox Code Playgroud)
由于在多个过程中使用了相同的代码,我想我会创建一个日期从 2005-01-01 到 2039-01-01 的表:
CREATE TABLE Dates(
[Date] DATE NOT NULL PRIMARY KEY
)
Run Code Online (Sandbox Code Playgroud)
该表是从具有日期维度的仓库中填充的。
所以,我写的不是那个 RIGHT JOIN,而是:
FROM Dates d
LEFT JOIN derived ON derived.Date …Run Code Online (Sandbox Code Playgroud) 所以我有一个我正在尝试优化的执行计划,并且有一段我不太明白的操作符。
计划中有一部分使用了计算标量,然后是使用哈希匹配的聚合。
我有一个问题:
如何使用哈希匹配聚合器的属性来告诉我它输出的是哪些列?我不知道正在对哪些列执行聚合。
这是运算符属性:
为元素规划 XML:
<RelOp NodeId="489" PhysicalOp="Hash Match" LogicalOp="Aggregate" EstimateRows="25432.8" EstimateIO="0" EstimateCPU="621.202" AvgRowSize="1038" EstimatedTotalSubtreeCost="12113" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
<OutputList>
<ColumnReference Database="[Staging]" Schema="[Junifer]" Table="[BillBreakdownLine]" Alias="[bbl]" Column="id" />
<ColumnReference Database="[Staging]" Schema="[Junifer]" Table="[BillBreakdownLine]" Alias="[bbl]" Column="description" />
<ColumnReference Database="[Staging]" Schema="[Junifer]" Table="[BillBreakdownLine]" Alias="[bbl]" Column="unitPrice" />
<ColumnReference Database="[Staging]" Schema="[Junifer]" Table="[BillBreakdownLine]" Alias="[bbl]" Column="units" />
<ColumnReference Database="[Staging]" Schema="[Junifer]" Table="[BillBreakdownLine]" Alias="[bbl]" Column="billCurrencyAmount" />
<ColumnReference Table="#BillLineCategorisation" Alias="[blc]" Column="Item" />
<ColumnReference Table="#BillLineCategorisation" Alias="[blc]" Column="InvoiceLineCategory" />
<ColumnReference Column="Expr1066" />
<ColumnReference Column="Expr1067" />
<ColumnReference Column="Expr1068" />
<ColumnReference Column="Expr1069" /> …Run Code Online (Sandbox Code Playgroud) 我有一个内部 Web 应用程序正在运行,每次用户转到“搜索”视图时,它都会查询数据库中的三个不同表,以生成视图中三个下拉列表的值。
它基本上运行一个
SELECT DISTINCT (PortName)
FROM Ports
ORDER BY PortName ASC
Run Code Online (Sandbox Code Playgroud)
但是该表包含约 10'000'000 行,并且负载非常重,这意味着页面的加载时间(由于加载数据下拉列表)可能会超过 10-15 秒。
那么,有没有更好的方法来做到这一点,例如以特定时间间隔运行一些脚本并在不同位置创建一个表/视图/任何内容,以便卸载查询大表,只是为了从 10'000 返回 80 行'000 在主表中?
我试图理解为什么我的查询需要很长时间,即使我已经索引了所需的列:
SELECT entity_id,
id,
report_date
FROM own_inst_detail
WHERE ( own_inst_detail.id = 'P7M7WC-S' )
AND ( own_inst_detail.report_date >= '2017-02-01T17:29:49.661Z' )
AND ( own_inst_detail.report_date <= '2018-08-01T17:29:49.663Z' )
Run Code Online (Sandbox Code Playgroud)
缓存结果EXPLAIN ANALYZE如下:
Bitmap Heap Scan on own_inst_detail (cost=20.18..2353.55 rows=597 width=22) (actual time=1.471..6.955 rows=4227 loops=1)
Recheck Cond: ((id = 'P7M7WC-S'::bpchar) AND (report_date >= '2017-06-01'::date) AND (report_date <= '2018-08-01'::date))
Heap Blocks: exact=4182
-> Bitmap Index Scan on own_inst_detail (cost=0.00..20.03 rows=597 width=0) (actual time=0.901..0.901 rows=4227 loops=1)
Index Cond: ((id = 'P7M7WC-S'::bpchar) AND (report_date >= '2017-06-01'::date) AND …Run Code Online (Sandbox Code Playgroud) postgresql performance optimization query-performance postgresql-performance
这是我在SQL Server 2008 R2, 2012,上测试过的复制品2016。
第二个和第三个查询确实使用了RowCount Spool,为什么第一个没有?
create table dbo.t (id int identity primary key, v int);
--create statistics ST_t__v on dbo.t(v) with norecompute;
insert into dbo.t (v)
select top (10000) rand(checksum(newid())) * 5
from master.dbo.spt_values a cross join
master.dbo.spt_values b;
go
declare @v int;
set statistics xml, io on;
select @v = v from dbo.t where exists(select 1 from dbo.t where v = 4);
select @v = v from dbo.t where exists(select …Run Code Online (Sandbox Code Playgroud) 我有以下版本的 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
我有一个FTS Catalog包含 ~10 6行的表。它曾经像魅力一样工作,但最近,由于未知原因,它开始随机出现非常糟糕的(查询> 30 秒)性能。
全文索引维护的阅读指南我仔细研究sys.fulltext_index_fragments并注意到以下几点:
这个波动的片段数量会干扰 SQL Server 的执行计划选择吗?
我能做些什么来清理这个?
performance sql-server optimization full-text-search sql-server-2014 query-performance
我们希望看到 SQL Server 优化器在查询优化期间考虑的查询计划的所有变体。SQL Server 使用querytraceon选项提供了非常详细的洞察力。例如,QUERYTRACEON 3604, QUERYTRACEON 8615允许我们打印出 MEMO 结构并QUERYTRACEON 3604, QUERYTRACEON 8619打印出在优化过程中应用的转换规则列表。这很好,但是,我们在跟踪输出方面有几个问题:
让我用一个更详细的例子来展示它。让我有两个人造表A和B:
WITH x AS (
SELECT n FROM
(
VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9)
) v(n)
),
t1 AS
(
SELECT ones.n + 10 * tens.n + 100 * hundreds.n + 1000 * thousands.n + 10000 * tenthousands.n + …Run Code Online (Sandbox Code Playgroud) 我有一个索引视图的适度用例,它折叠一列并总结一个大表中的所有条目:
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 …
我用一些测试数据更新了这篇文章。
我正在为我的电影数据库创建一个报告,我希望最终用户能够选择某种类型的电影。然而,有些电影有多种类型,我已经规范化了数据库,以便具有多个类型的电影订单项变成多个订单项,每个订单项都指向相应的类型/类型 ID。(对于董事也做了类似的事情)。
标准化前
| 电影 | 类型 |
|---|---|
| 弗兰肯斯坦的新娘 | 恐怖、剧情 |
标准化后
| 电影 | 类型 |
|---|---|
| 弗兰肯斯坦的新娘 | 恐怖 |
| 弗兰肯斯坦的新娘 | 戏剧 |
我遇到的问题是,为了这份报告,我希望做到这样,如果电影有多种类型,那么它们就不会在报告中重复。相反,电影标题成为一个行项目,并且流派字段被连接起来以显示一行内的所有流派(类似于标准化之前的视图)。我最终要做的是创建一个视图,在其中按照与电影 ID 匹配的类型交叉应用电影选择的输出。我觉得我有点过于复杂了,而且我的商店程序运行得相当慢,因为我还有其他几个字段允许用户进行过滤。
下面是交叉应用视图。
ALTER VIEW [dbo].[vwMoviesJoinedGenres] AS
WITH genreMovies_CTE AS (
SELECT M.MovieID
, M.MovieTitle
, G.GenreName
, G.GenreID
, M.TitleTypeID
, TT.TitleType
, M.MediaID
, M.IMDBLink
, M.IMDBRating
, M.ReleaseDate
, M.Runtime
, M.ImageURL
, M.MovieYear
FROM [dbo].[Movies] AS M
INNER JOIN GenresMovies AS GM
ON GM.MovieID = M.MovieID
INNER JOIN Genres AS G
ON G.GenreID = GM.GenreID
INNER JOIN TitleType AS TT …Run Code Online (Sandbox Code Playgroud) optimization ×10
sql-server ×9
performance ×2
t-sql ×2
cross-apply ×1
hints ×1
postgresql ×1
statistics ×1