标签: execution-plan

为什么 COALESCE 会阻止在 varchar 上使用索引,但不会阻止在文本列上使用索引?

想象一个视图,其中包含来自两个不同表的COALESCEvarchar列。

底层证券varchars在两个表中都有索引。

在 Postgres 11.6 中,根据结果过滤此视图COALESCE不使用索引,而是进行表扫描。

但是,如果我将列更改为text,在同一列上过滤完全相同的视图,则索引将按您的预期使用。

例子

假设我有一个一些标识符随时间变化的测量值表。还有一个几乎相同的表,其中包含估计值:

CREATE TABLE measured (
  id int,
  ts timestamp,
  identifier character varying,
  measured_value int
);
CREATE INDEX ON measured(identifier);

CREATE TABLE estimated (
  id int,
  ts timestamp,
  identifier character varying,
  estimated_value int
);
CREATE INDEX ON estimated(identifier);
Run Code Online (Sandbox Code Playgroud)

每个表有 100 万行数据:

INSERT INTO measured
SELECT
    generate_series(1, 1000000),
    to_timestamp((random() * 100000)::int),
    left(md5(random()::text), 2),
    random() * 10;

INSERT INTO estimated
SELECT
    generate_series(1, 1000000),
    to_timestamp((random() * …
Run Code Online (Sandbox Code Playgroud)

postgresql varchar execution-plan index-tuning postgresql-performance

5
推荐指数
1
解决办法
1951
查看次数

where 子句中的 dateadd - 在这种特定情况下如何避免完全扫描?

我有以下查询:

SELECT      u.userId,
            app.applicationId
FROM        app.application                 AS app
INNER JOIN  app.applicant                   AS ap   
            ON ap.applicantId = app.applicantId
INNER JOIN  usr.[user]                      AS u    
            ON u.userId = ap.userId
LEFT JOIN   msg.emailTemplateSent           AS t    
            ON t.toUserId = u.userId 
           AND t.emailTemplateName = 'v4_before_sixWeek_latestFlight_reminder'

WHERE       Convert(Date, GETUTCDATE())  = 
            DATEADD(week,-6,Convert(Date, app.flightDateLatest ))

AND         t.emailEventId IS NULL

ORDER BY    app.applicationId ASC
Run Code Online (Sandbox Code Playgroud)

请再次注意where子句的第一行:

Convert(Date, GETUTCDATE())  = DATEADD(week,-6,Convert(Date, app.flightDateLatest ))
Run Code Online (Sandbox Code Playgroud)

我可以以可以使用我的索引的方式更改此设置吗?索引实际上被使用了,但它是一个完整的扫描。

在此输入图像描述

也可以在这里看到:

在此输入图像描述

这是我的索引定义:

USE [APCore];
CREATE NONCLUSTERED INDEX i_flightDateLatest  
ON [app].[application] ( flightDateLatest  ASC  )  
INCLUDE ( [applicantId] , …
Run Code Online (Sandbox Code Playgroud)

index sql-server execution-plan sql-server-2016 query-performance

5
推荐指数
1
解决办法
1251
查看次数

Postgres 可以向后扫描索引吗?

我们使用 Amazon RDS 实例

x86_64-pc-linux-gnu 上的 PostgreSQL 11.13,由 gcc (GCC) 7.3.1 20180712 (Red Hat 7.3.1-12) 编译,64 位

我有一个简单的经典每组前 1 名查询。我需要获取每个 的历史记录中的最新项目creativeScheduleId

这是表和索引的定义:

CREATE TABLE IF NOT EXISTS public.creative_schedule_status_histories (
  id serial PRIMARY KEY,
  "creativeScheduleId" text NOT NULL,
  -- other columns
);

CREATE UNIQUE INDEX IF NOT EXISTS idx_creativescheduleid_id
  ON public.creative_schedule_status_histories ("creativeScheduleId" ASC, id ASC);
Run Code Online (Sandbox Code Playgroud)

当引擎的查询排序时id ASC仅读取索引并且不执行任何额外的排序:

EXPLAIN (ANALYZE) 
SELECT history.id, history."creativeScheduleId"
FROM  (
    SELECT cssh.id, cssh."creativeScheduleId"
         , ROW_NUMBER() OVER (PARTITION BY cssh."creativeScheduleId"
                              ORDER BY cssh.id ASC) …
Run Code Online (Sandbox Code Playgroud)

postgresql index execution-plan window-functions greatest-n-per-group

5
推荐指数
1
解决办法
516
查看次数

如何优化两个索引列上的 PostgreSQL OR 查询

我有一个大型分区表,用于存储帐户之间的货币交易。

CREATE TABLE "transactions" (
  "from" BYTEA        NOT NULL  -- sender account
  ,"to" BYTEA         NOT NULL  -- receiver account
  ,"type" INTEGER     NOT NULL  -- type of transfer
  ,"ts" TIMESTAMP     NOT NULL  -- timestamp of transfer
) PARTITION BY RANGE ("ts");
Run Code Online (Sandbox Code Playgroud)

“transactions”在“ts”、“from”和“to”上有索引(“ts”用于排序)。

CREATE INDEX "transactions_ts_idx"   ON "transactions" USING BTREE ("ts");
CREATE INDEX "transactions_from_idx" ON "transactions" USING BTREE ("from", "ts");
CREATE INDEX "transactions_to_idx"   ON "transactions" USING BTREE ("to",   "ts");
Run Code Online (Sandbox Code Playgroud)

我想查询涉及给定帐户或没有帐户的所有交易,例如:

-- given an account <account>
SELECT * FROM "transactions"
WHERE "from" = …
Run Code Online (Sandbox Code Playgroud)

postgresql index execution-plan index-tuning query-performance

5
推荐指数
1
解决办法
376
查看次数

SQL Server 生成具有并行性和 TOP 语句的查询计划

我有两个简单的查询:

SELECT TOP(20) * FROM Clients ORDER BY City
Run Code Online (Sandbox Code Playgroud)
SELECT TOP(20) Id, Name, City FROM Clients ORDER BY City
Run Code Online (Sandbox Code Playgroud)

在第一种情况下我得到这样的结果

ID 姓名 城市 更多专栏
6 6人 无效的 ...
2 2人 无效的 ...
3 3号人 无效的 ...

在第二种情况下,我得到这样的结果 在第一种情况下,我得到这样的结果

ID 姓名 城市
2 2人 无效的
3 3号人 无效的
6 6人 无效的

请注意,顺序不同。当然,我理解,因为 City 对于这三个人来说是 NULL,所以不一定能保证唯一的顺序。

然而,在检查查询计划时,我注意到第一个查询使用了并行性 在此输入图像描述

第二个查询没有:

在此输入图像描述

在阅读有关并行查询处理的文档后,它特别提到某些构造会抑制并行性,例如 TOP 运算符。

除了并行性之外,唯一显着的区别是并行计划的 Top N Sort 节点的估计 I/O 成本为 16,而非并行查询计划的 Top N Sort 节点仅具有估计 I/O 成本成本0.01

所以我的问题是:为什么当我使用 TOP 运算符时它仍然会使用并行性,即使微软声明它应该抑制该机制?

sql-server parallelism execution-plan

5
推荐指数
1
解决办法
305
查看次数

分区视图聚合查询未优化

给出以下两个表:

CREATE TABLE SalesLedger (
  Id int PRIMARY KEY IDENTITY,
  Date date NOT NULL,
  Total decimal(38,18),
  INDEX IX (Date, Total)
);

CREATE TABLE Purchases (
  Id int PRIMARY KEY IDENTITY,
  Date date NOT NULL,
  Total decimal(38,18),
  INDEX IX (Date, Total)
);
Run Code Online (Sandbox Code Playgroud)

以及下面的视图

CREATE VIEW ViewMetrics
AS

Select
  Date,
  'Sale' as Metric,
  Total as Value
From SalesLedger

UNION ALL

Select
  Date,
  'Purchase' as Metric,
  Total as Value
From Purchases;
Run Code Online (Sandbox Code Playgroud)

以下查询使用一Concatenation Sort对:

Select SUM(Value) as Sales, Date
from ViewMetrics …
Run Code Online (Sandbox Code Playgroud)

sql-server optimization execution-plan

5
推荐指数
1
解决办法
181
查看次数

NHibernate 如何处理执行计划?

我从播客中听说没有 ORM 可以很好地解决执行计划重用问题。它会导致执行计划缓存增加,从而影响性能。

  • NHibernate 如何处理执行计划?
  • 执行计划是否在 NHibernate 中重用?

sql-server orm execution-plan

4
推荐指数
2
解决办法
1585
查看次数

两个几乎相同的实例中的相同查询如何生成两个不同的执行计划?

服务器 A 和服务器 B 具有相同的硬件和实例配置(A 是生产,B 是 QA)。B 的数据库是从一周前 A 的备份中恢复的。开发团队向我提供了这个查询。

SELECT 
        c.Start
        ,c.[End]
        ,c.Word
        ,doc.UniqueDocumentNumber
        ,doc.EID
        ,c.CUI
        ,c.Concept
        ,a.OID
        ,doc.DocumentTypeName
        ,doc.ActivityDtTm
        ,CAST(doc.DocumentTypeId AS INT) AS MedCode
        ,CASE WHEN c.[Count] = 0 THEN  CAST(0.00 AS REAL)
           ELSE CAST(LOG(c.TotalCount / c.[Count]) AS REAL) END AS 'idf'
        ,c.[Count]
        ,c.TotalCount
FROM ECHO..AEID201 a
INNER JOIN ALPHA..XADocuments doc (NOLOCK) ON a.EID = doc.EID
CROSS APPLY (SELECT t.start,t.[end],t.word,t.cui,t.eid,
   t.UniqueDocumentNumber,cu.[Count],cc.TotalCount,core.Concept 
FROM HOTEL.dbo.Htf_Index AS t
INNER JOIN HOTEL..Doc_CUI_Counter AS cu ON cu.CUI=t.CUI AND cu.DocumentTypeID=t.DocumentTypeID
INNER JOIN HOTEL..Doc_Counter …
Run Code Online (Sandbox Code Playgroud)

execution-plan sql-server-2008-r2 subquery functions cross-apply

4
推荐指数
1
解决办法
577
查看次数

使用 WHERE NOT IN 子选择子句提高性能

在以下查询中,我必须为每个客户计算交易。但是,我必须从结果集中完全排除交易时间超过一年的客户。

查询优化器不应该足够聪明,只为每个客户评估一次存在吗?

--Count transactions on customers that are less than 1 year old

SELECT t1.CUSTID, COUNT(*)
FROM CUST_TRX t1
WHERE NOT EXISTS ( 
  SELECT FIRST 1 1 
  FROM CUST_TRX t2 
  WHERE 
    t2.CUSTID = t1.CUSTID AND
    t2.DATED < CURRENT_DATE - 365
  GROUP BY t2.CUSTID
)
GROUP BY t1.CUSTID
Run Code Online (Sandbox Code Playgroud)

我的查询计划中没有自然。此查询的执行就像数据库为每个事务运行存在子句,而不是为每个客户运行它。如果我删除GROUP BY子查询中的,则性能相同。

有没有更好的方法来做到这一点,以便我可以从数据库中获得更好的性能?SELECT如果可能的话,希望一个简单的查询能够避免 CTE(这会带来其他挑战)。

由于其他GROUP BY条件(此处未显示),我无法简单地检查MIN(DATED),我确实需要执行另一个查询。

performance execution-plan subquery firebird query-performance

4
推荐指数
1
解决办法
7679
查看次数

为什么要进行聚集索引扫描?

我刚刚开始学习优化我的查询并分析他们的查询计划。我认为这个查询会生成非聚集索引查找 + 键查找。

SELECT ct.*
FROM Person.ContactType AS ct
WHERE ct.Name LIKE 'Own%';
Run Code Online (Sandbox Code Playgroud)

相反,它使用聚集索引扫描。我不知道为什么。

我正在 SQL Server 2012 Express 上使用 AdventureWorks2012 数据库。ContactTypeId 列上有聚集索引,Name 列上有非聚集索引。第三列 (ModifiedDate) 不属于任何索引。该表仅包含 20 行。

我怀疑查询优化器决定进行聚集索引扫描,因为表只有 20 行,也许扫描索引然后进行键查找更快。

sql-server execution-plan sql-server-2012 sql-server-express

4
推荐指数
1
解决办法
1194
查看次数