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 / 问题 / 162798
Accepted
Jmaurier
Jmaurier
Asked: 2017-02-01 13:42:14 +0800 CST2017-02-01 13:42:14 +0800 CST 2017-02-01 13:42:14 +0800 CST

数据类型会影响视图的性能吗?

  • 772

我刚刚注意到,在我们的数据库中,我们有一个将BIT列转换为INT. 基础表有一个计算BIT列,其定义如下:

IncludeInJobTotals as (CONVERT(bit, 
case 
when FL.[Status]=(5) 
  or FL.[Status]=(3)
  or FL.[Status]=(2) 
then (1) 
else (0) 
end,(0)))

在使用的视图中,IncludeInJobTotals我们将其转换为INT. 这会导致任何性能问题吗?可能还有哪些问题?有什么理由使用INToverBIT吗?

sql-server
  • 1 1 个回答
  • 107 Views

1 个回答

  • Voted
  1. Best Answer
    Joe Obbish
    2017-02-01T18:01:19+08:002017-02-01T18:01:19+08:00

    首先回答一般性问题,是的,视图中的数据类型绝对会影响性能。让我们模拟一些数据来说明一个简单的例子:

    DROP TABLE IF EXISTS X_162798;
    
    CREATE TABLE X_162798 (
    NUM_VARCHAR VARCHAR(10), 
    NUM_INT INT,
    [Status] INT,
    IncludeInJobTotals as (CONVERT(bit, 
    case 
    when [Status]=(5) 
      or [Status]=(3)
      or [Status]=(2) 
    then (1) 
    else (0) 
    end,(0)))
    );
    
    -- insert 1 M rows with 999990 of them having a value of 1 for IncludeInJobTotals
    WITH
      L0   AS(SELECT 1 AS c UNION ALL SELECT 1),
      L1   AS(SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
      L2   AS(SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
      L3   AS(SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
      L4   AS(SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
      L5   AS(SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
      Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS n FROM L5)
    INSERT INTO X_162798 WITH (TABLOCK)
    SELECT 
    CAST(n AS VARCHAR(10))
    , n
    , CASE WHEN n <= 10 THEN 0 ELSE 5 END
    FROM Nums 
    WHERE n <= 1000000;
    
    UPDATE STATISTICS X_162798 WITH FULLSCAN;
    
    -- index all the columns
    CREATE INDEX IX_162798_NUM_VARCHAR ON X_162798 (NUM_VARCHAR);
    CREATE INDEX IX_162798_NUM_INT ON X_162798 (NUM_INT);
    CREATE INDEX IX_162798_STATUS ON X_162798 ([Status]);
    CREATE INDEX IX_162798_JOB ON X_162798 (IncludeInJobTotals);
    
    DROP VIEW IF EXISTS V_162798;
    
    GO
    
    CREATE VIEW V_162798
    AS
    SELECT
    CAST(NUM_VARCHAR AS INT) NUM_INT_CASTED
    , NUM_VARCHAR 
    , IncludeInJobTotals
    , CONVERT(INT, IncludeInJobTotals) IncludeInJobTotals_INT
    FROM X_162798;
    
    GO
    

    以下两个查询返回相同的结果,但性能却大不相同:

    -- this query does a table scan and does an estimate based on density
    SELECT *
    FROM V_162798
    WHERE NUM_INT_CASTED = '1';
    
    -- this query does an index seek and does an estimate based on the histogram 
    SELECT *
    FROM V_162798
    WHERE NUM_VARCHAR = '1';
    

    执行计划

    如果我进行了错误的数据类型转换,过滤器将不再可优化搜索。它不能在列上使用索引,并且基数估计会因为不能使用直方图而受到影响。

    BIT在您将列投射到 an 的情况下是否重要INTEGER?我们可以过滤视图中的IncludeInJobTotals和IncludeInJobTotals_INT列以运行一些测试。基于数据类型优先级,我们应该期望在 a和 an之间的任何比较中 aBIT将转换为an 。SQL Server应该能够在它们之间进行隐式转换,所以我认为很难找到性能问题。INTEGERBITINTEGER

    由于我们处理的是位列,因此简单过滤器的可能测试用例并不多。如果我在视图的任一列上过滤以查找具有0值的行,我总是会得到索引查找和正确的基数估计:

    -- all queries do an index seek and estimate 10 rows will be returned
    SELECT NUM_VARCHAR
    FROM V_162798
    WHERE IncludeInJobTotals = 0;
    
    SELECT NUM_VARCHAR
    FROM V_162798
    WHERE IncludeInJobTotals_INT = 0;
    
    SELECT NUM_VARCHAR
    FROM V_162798
    WHERE IncludeInJobTotals = CAST(0 AS BIT);
    
    SELECT NUM_VARCHAR
    FROM V_162798
    WHERE IncludeInJobTotals_INT = CAST(0 AS BIT);
    

    如果我过滤视图的任一列以查找具有1值的行,我总是会得到表扫描和正确的基数估计:

    -- all queries do a table scan and estimate 999990 rows will be returned
    SELECT NUM_VARCHAR
    FROM V_162798
    WHERE IncludeInJobTotals = 1;
    
    SELECT NUM_VARCHAR
    FROM V_162798
    WHERE IncludeInJobTotals_INT = 1;
    
    SELECT NUM_VARCHAR
    FROM V_162798
    WHERE IncludeInJobTotals = CAST(1 AS BIT);
    
    SELECT NUM_VARCHAR
    FROM V_162798
    WHERE IncludeInJobTotals_INT = CAST(1 AS BIT);
    

    寻找超出范围的值也按预期工作:

    -- these queries do an index seek and estimate 1 row will be returned
    SELECT NUM_VARCHAR
    FROM V_162798
    WHERE IncludeInJobTotals = 2;
    
    SELECT NUM_VARCHAR
    FROM V_162798
    WHERE IncludeInJobTotals_INT = 2;
    

    我不会担心这种数据类型更改的性能。很难想象您会遇到性能问题的场景。但是,请务必注意,使用视图的查询可能会根据您使用列的方式返回不同的结果。BIT数据类型的行为不同于INT:

    转换为位会将任何非零值提升为 1。

    回到数据类型优先级列表,一个VARCHAR值将被转换为一个BIT值。这意味着获得不同结果的一种方法是过滤或加入超出范围的VARCHAR值:

    CREATE TABLE TABLE_WITH_THE_NUMBER_2 (NUM VARCHAR(1));
    INSERT INTO TABLE_WITH_THE_NUMBER_2 VALUES ('2');
    
    -- this query returns 999990
    SELECT COUNT(*)
    FROM V_162798 v
    INNER JOIN TABLE_WITH_THE_NUMBER_2 t ON v.IncludeInJobTotals = t.NUM;
    
    -- this query returns 0
    SELECT COUNT(*)
    FROM V_162798 v
    INNER JOIN TABLE_WITH_THE_NUMBER_2 t ON v.IncludeInJobTotals_INT = t.NUM;
    

    也许您的应用程序永远不会这样做,但您希望在那种情况下发生什么?我会在这里关注正确性而不是性能。

    • 3

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

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

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