标签: execution-plan

为什么我的计划指南没有被使用?

我们最近遇到了临界点问题,我们的一些报告查询过去需要在几秒钟内完成执行,现在需要超过 2 分钟,因为查询优化器只是忽略了搜索列上的非聚集索引。下面是一个示例查询:

select top 100 *
from   [dbo].[t_Call]
where  ID > 0 
  and  throwtime between '3/20/2014 7:00:00 AM' and '3/24/2014 6:59:59 AM'
order by id
Run Code Online (Sandbox Code Playgroud)

ID列是聚集索引并且Throwtime具有非聚集索引。在这种情况下,我们注意到 ordering bythrowtime而不是ID更改查询计划和非聚集索引被使用。我们还计划存档一些旧数据(它目前有 2000 万行!!)。但是在应用程序中进行这些更改需要一些时间,我需要找到一种方法来使报告运行得相当快,而无需在应用程序级别进行更改(哦,这就是生活!)。

进入计划指南。我使用非聚集索引查询提示创建了以下计划指南,但出于某种原因,仍未使用非聚集索引。我错过了什么吗?

EXEC sp_create_plan_guide 
@name = N'[prod2reports_callthrowtime]', 
@stmt = N'select top 100 *
          from   [dbo] . [t_Call]
          where  ID > @0 and @1 < = ThrowTime and ThrowTime < = @2 order by ID',
@type = N'SQL', 
@module_or_batch = N'select …
Run Code Online (Sandbox Code Playgroud)

performance sql-server execution-plan plan-guides query-performance

9
推荐指数
1
解决办法
2784
查看次数

让 Postgresql 查询规划器在哈希连接上使用带有索引的嵌套循环

我在加载 PostgreSQL 9.3.4 时遇到了一些与 StackOverflow 模式相关的数据的问题。我有一个查询比它应该花费的时间长大约 10 倍,因为它选择使用散列连接而不是带有索引的嵌套循环。例如,如果我在查询中选择 500 个用户,则使用散列连接而不是使用 post_tokenized 表上的 id 和类型索引:

explain 
select creation_epoch, user_screen_name, chunk from post_tokenized as tokenized_tbl
                    join posts as posts_tbl
                    on posts_tbl.id = tokenized_tbl.id
                    where type = 'tag'
                    and user_screen_name is not null
                    and owner_user_id in (select id from users where reputation > 100000 order by reputation asc limit 500)
                    and tokenized_tbl.id in (select id from posts where owner_user_id in (select id from users where reputation > 100000 order by reputation asc limit …
Run Code Online (Sandbox Code Playgroud)

postgresql performance execution-plan query-performance

9
推荐指数
1
解决办法
1万
查看次数

未使用但影响查询的索引

我有一个 PostgreSQL 9.3 表,其中包含一些数字和一些附加数据:

CREATE TABLE mytable (
    myid BIGINT,
    somedata BYTEA
)
Run Code Online (Sandbox Code Playgroud)

该表目前有大约 10M 条记录,占用 1GB 磁盘空间。myid不连续。

我想计算 100000 个连续数字的每个块中有多少行:

SELECT myid/100000 AS block, count(*) AS total FROM mytable GROUP BY myid/100000;
Run Code Online (Sandbox Code Playgroud)

这将返回大约 3500 行。

我注意到某个索引的存在显着加快了这个查询,即使查询计划根本没有提到它。没有索引的查询计划:

db=> EXPLAIN (ANALYZE TRUE, VERBOSE TRUE) SELECT myid/100000 AS block, count(*) AS total FROM mytable GROUP BY myid/100000;
                                                               QUERY PLAN                                                               
----------------------------------------------------------------------------------------------------------------------------------------
 GroupAggregate  (cost=1636639.92..1709958.65 rows=496942 width=8) (actual time=6783.763..8888.841 rows=3460 loops=1)
   Output: ((myid / 100000)), count(*)
   ->  Sort  (cost=1636639.92..1659008.91 rows=8947594 width=8) (actual time=6783.752..8005.831 …
Run Code Online (Sandbox Code Playgroud)

postgresql index execution-plan count index-tuning

9
推荐指数
2
解决办法
1014
查看次数

未用于全表查询的分区索引统计

在对分区进行连接时与在整个表上进行连接时,以下连接具有非常不同的行估计:

CREATE TABLE m_data.ga_session (
  session_id         BIGINT                   NOT NULL,
  visitor_id         BIGINT                   NOT NULL,
  transaction_id     TEXT,

  timestamp          TIMESTAMP WITH TIME ZONE NOT NULL,
  day_id             INTEGER                  NOT NULL,
  [...]

  device_category    TEXT                     NOT NULL,
  [...]
  operating_system   TEXT

);
Run Code Online (Sandbox Code Playgroud)

对于所有分区:

CREATE TABLE IF NOT EXISTS m_data.ga_session_20170127 ( CHECK (day_id = 20170127) ) INHERITS (m_data.ga_session);
-- the identifier are theoretically invalid, but they get truncated to 63 chars and nevertheless work
CREATE INDEX IF NOT EXISTS "ga_session__m_tmp.normalize_device_category(ga_session.device_category)" on m_data.ga_session_20170127 USING btree (m_tmp.normalize_device_category(device_category)) ;
CREATE INDEX …
Run Code Online (Sandbox Code Playgroud)

postgresql execution-plan postgresql-9.5

9
推荐指数
1
解决办法
405
查看次数

为什么在我的分区视图上执行删除会导致聚集索引插入?

我有一个分区视图,其中包含以下插入触发器(可怜的 mans 分区)。当我执行 DELETE 时,我得到以下查询计划:

delete from factproductprice where pricedate = '20170725'
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

在视图上触发:

ALTER TRIGGER [dbo].[factProductPriceDelete] ON [dbo].[FactProductPrice]
INSTEAD OF DELETE AS
BEGIN
  IF @@ROWCOUNT = 0 RETURN;

  DECLARE @PriceDate DATE
  SELECT @PriceDate = CAST(PriceDate AS DATE) FROM DELETED
  IF @PriceDate BETWEEN '20140101' AND '20141231'
  BEGIN
    DELETE FROM dbo.FactProductPrice2014
    WHERE ProductId IN (SELECT ProductId FROM DELETED) AND SalesPriceSchemeId IN (SELECT SalesPriceSchemeId FROM DELETED) AND PriceDate IN (SELECT PriceDate FROM DELETED) 
  END
  IF @PriceDate BETWEEN '20150101' AND '20151231'
  BEGIN
    DELETE FROM …
Run Code Online (Sandbox Code Playgroud)

trigger sql-server execution-plan partitioning sql-server-2014

9
推荐指数
1
解决办法
144
查看次数

主/明细表之间的散列连接产生过低的基数估计

将主表连接到详细表时,如何鼓励 SQL Server 2014 使用较大(详细)表的基数估计作为连接输出的基数估计?

例如,当将 10K 主行连接到 100K 详细行时,我希望 SQL Server 估计连接为 100K 行——与估计的详细行数相同。我应该如何构建我的查询和/或表和/或索引以帮助 SQL Server 的估算器利用每个详细信息行始终具有相应的主行这一事实?(这意味着它们之间的连接永远不应该减少基数估计。)

这里有更多细节。我们的数据库有一对主/明细表:VisitTarget每个销售交易占一行,每个交易VisitSale中的每个产品占一行。这是一个一对多的关系:一个 VisitTarget 行平均有 10 个 VisitSale 行。

表格如下所示:(我正在简化为仅针对此问题的相关列)

-- "master" table
CREATE TABLE VisitTarget
(
  VisitTargetId int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
  SaleDate date NOT NULL,
  StoreId int NOT NULL
  -- other columns omitted for clarity  
);
-- covering index for date-scoped queries
CREATE NONCLUSTERED INDEX IX_VisitTarget_SaleDate 
    ON VisitTarget (SaleDate) INCLUDE (StoreId /*, ...more columns */);

-- …
Run Code Online (Sandbox Code Playgroud)

sql-server execution-plan sql-server-2014 cardinality-estimates

9
推荐指数
1
解决办法
683
查看次数

是什么导致此查询/执行计划的 CPU 使用率过高?

我有一个支持 .NET Core API 应用程序的 Azure SQL 数据库。浏览 Azure 门户中的性能概览报告表明,我的数据库服务器上的大部分负载(DTU 使用情况)来自 CPU,特别是一个查询:

在此处输入图片说明

正如我们所见,查询 3780 负责几乎所有服务器上的 CPU 使用率。

这在某种程度上是有道理的,因为查询 3780(见下文)基本上是整个应用程序的关键,并且经常被用户调用。这也是一个相当复杂的查询,需要许多连接才能获得所需的正确数据集。查询来自一个最终看起来像这样的 sproc:

-- @UserId UNIQUEIDENTIFIER

SELECT
    C.[Id],
    C.[UserId],
    C.[OrganizationId],
    C.[Type],
    C.[Data],
    C.[Attachments],
    C.[CreationDate],
    C.[RevisionDate],
    CASE
        WHEN
            @UserId IS NULL
            OR C.[Favorites] IS NULL
            OR JSON_VALUE(C.[Favorites], CONCAT('$."', @UserId, '"')) IS NULL
        THEN 0
        ELSE 1
    END [Favorite],
    CASE
        WHEN
            @UserId IS NULL
            OR C.[Folders] IS NULL
        THEN NULL
        ELSE TRY_CONVERT(UNIQUEIDENTIFIER, JSON_VALUE(C.[Folders], CONCAT('$."', @UserId, '"')))
    END [FolderId],
    CASE 
        WHEN C.[UserId] IS NOT NULL OR …
Run Code Online (Sandbox Code Playgroud)

performance sql-server execution-plan azure-sql-database cpu query-performance

9
推荐指数
1
解决办法
6637
查看次数

“警告:操作导致残留 I/O”与键查找

我在 SQL Server 2017 执行计划中看到过这个警告:

警告:操作导致剩余 IO [原文如此]。实际读取的行数为 (3,321,318),但返回的行数为 40。

这是 SQLSentry PlanExplorer 的一个片段:

在此处输入图片说明

为了改进代码,我添加了一个非聚集索引,以便 SQL Server 可以访问相关行。它工作正常,但通常会有太多(大)列包含在索引中。它看起来像这样:

在此处输入图片说明

如果我只添加索引而不包含列,如果我强制使用索引,它看起来像这样:

在此处输入图片说明

显然,SQL Server 认为键查找比剩余 I/O 昂贵得多。我有一个没有太多测试数据的测试设置(还),但是当代码投入生产时,它需要处理更多的数据,所以我很确定需要某种非聚集索引。

当您在 SSD 上运行时,键查找真的那么昂贵,我必须创建全脂索引(有很多包含列)?


执行计划: https : //www.brentozar.com/pastetheplan/?id=SJtiRte2X它是长存储过程的一部分。寻找IX_BatchNo_DeviceNo_CreatedUTC.

sql-server optimization execution-plan nonclustered-index sql-server-2017

9
推荐指数
1
解决办法
4312
查看次数

缺少非聚集索引已经是聚集索引的一部分

我正在调试运行缓慢的查询,并且在执行计划中建议使用非聚集索引,影响为 51.6648。但是,非聚集索引仅包括主键 (PK) 复合聚集索引中已经存在的列。

这可能是因为索引中列的顺序吗?即,如果聚集索引中的列不是按选择性从高到低的顺序排列,那么非聚集索引是否有可能提高性能?

此外,非聚集索引仅包含三个 PK 列中的两个,第三个添加为包含列。include使用非聚集索引可能更优化的另一个原因是什么?

下面是我正在使用的表结构的示例:

表-

Retailers (
    RetailerID int PK, 
    name ...)

Retailer_Relation_Types (
    RelationType smallint PK, 
    Description nvarchar(50) ...)

Retailer_Relations (
    RetailerID int PK FK, 
    RelatedRetailerID int PK FK, 
    RelationType smallint PK FK, 
    CreatedOn datetime ...)
Run Code Online (Sandbox Code Playgroud)

该表Retailer_Relations具有以下复合PK指数和建议指数-

CONSTRAINT PK_Retailer_Relations 
PRIMARY KEY CLUSTERED (
    RetailerID ASC, 
    RelatedRetailerID ASC, 
    RelationType ASC
    ) ON [PRIMARY]

CREATE NONCLUSTERED INDEX <NameOfIndex> 
ON Retailer_Relations (
    RetailerID, 
    RelationType
    ) 
INCLUDE (
    RelatedRetailerID
    )
Run Code Online (Sandbox Code Playgroud)

index sql-server execution-plan sql-server-2016

9
推荐指数
1
解决办法
895
查看次数

取消旋转单行时如何摆脱无用的并行分支?

考虑以下查询,该查询对少量标量聚合进行了反透视:

SELECT A, B
FROM (
    SELECT 
      MAX(CASE WHEN ID = 1 THEN 1 ELSE 0 END) VAL1
    , MAX(CASE WHEN ID = 2 THEN 1 ELSE 0 END) VAL2
    , MAX(CASE WHEN ID = 3 THEN 1 ELSE 0 END) VAL3
    , MAX(CASE WHEN ID = 4 THEN 1 ELSE 0 END) VAL4
    , MAX(CASE WHEN ID = 5 THEN 1 ELSE 0 END) VAL5
    , MAX(CASE WHEN ID = 6 THEN 1 ELSE 0 END) VAL6
    , MAX(CASE …
Run Code Online (Sandbox Code Playgroud)

sql-server parallelism execution-plan sql-server-2017

9
推荐指数
2
解决办法
480
查看次数