标签: optimization

即使新查询的逻辑读取比旧查询少,它也更慢

我在存储过程中有一个查询,它必须列出一个范围内的所有日期,并从表中加入日期(如果当天存在的话)。

这个过程是在我成为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)

sql-server optimization statistics

6
推荐指数
1
解决办法
1338
查看次数

帮助解释执行计划(哈希聚合)

所以我有一个我正在尝试优化的执行计划,并且有一段我不太明白的操作符。

计划中有一部分使用了计算标量,然后是使用哈希匹配的聚合。

我有一个问题:

如何使用哈希匹配聚合器的属性来告诉我它输出的是哪些列?我不知道正在对哪些列执行聚合。

这是计划的部分: 在此处输入图片说明

这是运算符属性:

在此处输入图片说明

为元素规划 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)

sql-server optimization execution-plan

6
推荐指数
1
解决办法
221
查看次数

每次在大表上运行查询很少更改的数据的替代方法

我有一个内部 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 在主表中?

sql-server optimization t-sql sql-server-2014

6
推荐指数
3
解决办法
2413
查看次数

优化位图堆扫描

我试图理解为什么我的查询需要很长时间,即使我已经索引了所需的列:

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

6
推荐指数
1
解决办法
9102
查看次数

为什么第一个执行计划不使用 RowCount Spool?

这是我在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 optimization execution-plan

6
推荐指数
1
解决办法
207
查看次数

为什么 SQL 不使用索引视图?

我有以下版本的 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

6
推荐指数
1
解决办法
588
查看次数

振荡的片段数量会降低 FTS 查询性能吗?

我有一个FTS Catalog包含 ~10 6行的表。它曾经像魅力一样工作,但最近,由于未知原因,它开始随机出现非常糟糕的(查询> 30 秒)性能。

全文索引维护的阅读指南我仔细研究sys.fulltext_index_fragments并注意到以下几点:

  1. 片段数量在2到20之间高频振荡(每分钟多次);
  2. 最大的片段包含约 10 5行,大小为 11Mb;
  3. 其他包含 1 到 40 行。

这个波动的片段数量会干扰 SQL Server 的执行计划选择吗?

我能做些什么来清理这个?

performance sql-server optimization full-text-search sql-server-2014 query-performance

6
推荐指数
1
解决办法
117
查看次数

SQL Server优化过程揭秘

我们希望看到 SQL Server 优化器在查询优化期间考虑的查询计划的所有变体。SQL Server 使用querytraceon选项提供了非常详细的洞察力。例如,QUERYTRACEON 3604, QUERYTRACEON 8615允许我们打印出 MEMO 结构并QUERYTRACEON 3604, QUERYTRACEON 8619打印出在优化过程中应用的转换规则列表。这很好,但是,我们在跟踪输出方面有几个问题:

  1. 似乎 MEMO 结构只包含查询计划的最终变体或后来被重写为最终变体的变体。有没有办法找到“不成功/没有希望”的查询计划?
  2. MEMO 中的运算符不包含对 SQL 部分的引用。例如,LogOp_Get 运算符不包含对特定表的引用。
  3. 转换规则不包含对 MEMO 运算符的精确引用,因此,我们无法确定转换规则转换了哪些运算符。

让我用一个更详细的例子来展示它。让我有两个人造表AB

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)

sql-server optimization

6
推荐指数
1
解决办法
279
查看次数

实际执行计划中未使用索引视图?

我有一个索引视图的适度用例,它折叠一列并总结一个大表中的所有条目:

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 …

sql-server optimization materialized-view sql-server-2016

6
推荐指数
1
解决办法
227
查看次数

是否有更优化的方法来创建此视图或存储过程?目前使用交叉应用,但速度很慢

我用一些测试数据更新了这篇文章。

我正在为我的电影数据库创建一个报告,我希望最终用户能够选择某种类型的电影。然而,有些电影有多种类型,我已经规范化了数据库,以便具有多个类型的电影订单项变成多个订单项,每个订单项都指向相应的类型/类型 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)

sql-server stored-procedures optimization t-sql cross-apply

6
推荐指数
1
解决办法
437
查看次数