AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 183486
Accepted
Nate
Nate
Asked: 2017-08-15 14:19:31 +0800 CST2017-08-15 14:19:31 +0800 CST 2017-08-15 14:19:31 +0800 CST

视图上的 SELECT COUNT(*) 比同一视图上的 SELECT * 慢几个数量级

  • 772

风景

CREATE VIEW [dbo].[vProductList]
WITH SCHEMABINDING
AS 

SELECT
     p.[Id]
    ,p.[Name]
    ,price.[Value] as CalculatedPrice
    ,orders.[Value] as OrdersWithThisProduct
FROM 
    products as p 
    INNER JOIN productMetadata as price ON p.Id = price.ProductId AND price.MetaId = 1
    INNER JOIN productMetadata as orders ON p.Id = orders.ProductId AND orders.MetaId = 2

为简单起见,假设productMetadatahas 列ProductId, MetaId, Value有大约 87m 行,并且表中有大约 400k 行products。

针对此视图的一般查询非常有效:

SELECT * FROM vProductList WHERE CalculatedPrice > 500

查询结果在 2-4 秒内(通过 vpn 和远程,所以我很擅长)。

将上述更改为计数同样快:

SELECT COUNT(*) from vProductList WHERE CalculatedPrice > 500

与原始选择大约在同一时间运行,我再次同意。大约有 10k 种产品符合此标准。

我遇到了两个不同的情况,事情变得非常奇怪并且永远持续下去。

第一的

对视图中基表中的一列进行查询:

SELECT * FROM vProductList WHERE Name = 'Hammer' 

这个查询需要一点时间来运行(20-30 秒)并返回大约 30k 的结果;但是,对所述查询稍作更改:

SELECT COUNT(*) FROM vProductList WHERE Name = 'Hammer' 

需要 13 分钟才能返回一个说明 ~30k 的计数。

第二

执行WHERE IN子查询

SELECT * FROM vProductList WHERE Id IN (SELECT ProductId FROM TableThatHasFKToProductId and ColumnInTable = 'Yes')

此查询返回约 300k 行,需要两分钟才能返回(我相信大部分时间只是花在将数据下载到 SSMS 中);但是,将其更改为SELECT COUNT(*)需要 20 分钟的查询。

SELECT COUNT(*) FROM vProductList WHERE Id IN (SELECT ProductId FROM TableThatHasFKToProductId and ColumnInTable = 'Yes')

为什么它SELECT *比 快SELECT COUNT?

我将 SSMS 提供的总执行时间用于此处列出的所有时间。

执行计划

计划SELECT 1 FROM v WHERE IN (...)

计划SELECT COUNT(0) FROM v WHERE IN (...)

注意:我尝试使用 PasteThePlan,但它一直告诉我的计划是无效的 xml。

performance view
  • 1 1 个回答
  • 3956 Views

1 个回答

  • Voted
  1. Best Answer
    Paul White
    2017-08-17T19:53:37+08:002017-08-17T19:53:37+08:00

    从提供的执行计划中,对于COUNT优化器围绕最终连接选择本地/全局聚合策略的情况:

    最终加入

    不幸的是,优化器高估了本地聚合的有效性。它估计有 136 行驱动嵌套循环连接,而在运行时遇到 366,115 行。

    估计

    对于本地 SQL Server 实例而言,366,115 次索引查找可能不是什么大问题,但计划中包含的等待统计信息显示了当前 Azure SQL 数据库配置的 I/O(可能还有内存)限制:

    等待统计

    该计划SELECT 1显示了一个专门的哈希和合并连接策略,在这种情况下,它会在内存和/或 I/O 能力非常有限的情况下产生更好的结果。

    您可能会看到带有OPTION (HASH JOIN, MERGE JOIN)提示的第一个查询的性能更好,但根本问题是由大量连接驱动的较差的基数/数据分布估计。

    不要被针对每个计划运算符显示的成本百分比所误导 - 这些数字目前来自优化器对成本的估计(使用抽象模型)。这些数字不反映运行时条件或成本。

    估计行数和实际行数之间的较大偏差通常会导致问题。对于导致优化器选择在特定硬件设置上不能很好扩展的策略的低估尤其如此。

    • 5

相关问题

  • 使用存储过程处理数据与在检索后将其输入函数相比是否有性能提升?

  • 您如何针对繁重的 InnoDB 工作负载调整 MySQL?

  • 如何确定是否需要或需要索引

  • 我在哪里可以找到mysql慢日志?

  • 如何优化大型数据库的 mysqldump?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve