zoukankan      html  css  js  c++  java
  • SELECT * 测试

    描述

    大家通常禁止在生产环境直接使用select * 已成常识了,也常常在开发规范中就会规定不允许直接使用select *,那么我们为什么不允许使用select * ,在一些什么场景下select * 会出问题?能否控制不能直接使用select *?出于这些疑问,我们特别测试记录一下。

     

    测试环境

    Microsoft SQL Server 2012 - 11.0.2100.60 (X64) 
    Feb 10 2012 19:39:15 
    Copyright (c) Microsoft Corporation
    Enterprise Edition (64-bit) on Windows NT 6.2 <X64> (Build 9200: )
     

    select * 可能会造成业务功能出错

    假设我们有一个视图 V_test 代码如下:
    1 CREATE VIEW v_test
    2 AS
    3     SELECT  *
    4     FROM    test
    你在web前端调用直接使用如下脚本并对应好显示的字段,当时功能是正常的。
       SELECT  *
        FROM    v_test
    test 表结构如下:
    后来因为业务调整,有人调整了test表 ,并加一个字段F ,那么接下来的后果就会前端相应的功能因新增的字段F直接报错。
     

    select * 可能会造成性能方面的问题

    测试数据准备
     1 --新建测试表
     2 IF OBJECT_ID('test', 'U') IS NOT NULL
     3     DROP TABLE test;
     4 CREATE TABLE test
     5     (
     6       id int IDENTITY(1, 1) ,
     7       a nvarchar(20) ,
     8       b nvarchar(15) ,
     9       c nvarchar(20) ,
    10       d int ,
    11       e float
    12     );
     1 --造测试数据
     2 DECLARE @i INT; 
     3 SET @i = 10000;
     4 WHILE ( @i > 0 )
     5     BEGIN 
     6         INSERT  INTO test
     7                 ( a ,
     8                   b ,
     9                   c ,
    10                   d ,
    11                   e
    12                 )
    13                 SELECT  RAND() * 1000 ,
    14                         RAND() * 1000 ,
    15                         REPLICATE('a', 3) ,
    16                         @i ,
    17                         @i - 1;
    18         SELECT  @i = @i - 1;
    19     END; 
    1 --新建索引(主键、非聚集索引)
    2 ALTER TABLE dbo.test ADD CONSTRAINT PK_test_id PRIMARY KEY(ID);
    3 CREATE INDEX IX_test_1 ON dbo.test(a);
    查询条件使用主键字段的执行计划,主键是默认覆盖全部字段。
    如直接使用字段a做查询条件
    还是聚集索引扫描,全表扫,无法使用我们已新建好的非聚集索引IX_test_1,在上述语句中因该索引未覆盖到非a 的字段。假设实际场景我们只需取a字段,那么执行计划又是怎么样的?
    如上图,就会走我们期望的索引,同时也可以减少因select * 而多读的字段(id、b、c、d、e)的网络传输,所以,尽量指定自己所需的字段名,可以避免一些无谓的性能开销。
     

    如何控制不让 select *

    假设我们不允许在上述测试表test上执行select * 可以如何处理
     1 --新建测试表
     2 IF OBJECT_ID('test', 'U') IS NOT NULL
     3     DROP TABLE test;
     4 CREATE TABLE test
     5     (
     6       id int IDENTITY(1, 1) ,
     7       a nvarchar(20) ,
     8       b nvarchar(15) ,
     9       c nvarchar(20) ,
    10       d int ,
    11       e float,
    12       abort_select_all  AS  (1/0)        ---新增控制字段
    13     );
    14 --造测试数据
    15 DECLARE @i INT; 
    16 SET @i = 10000;
    17 WHILE ( @i > 0 )
    18     BEGIN 
    19         INSERT  INTO test
    20                 ( a ,
    21                   b ,
    22                   c ,
    23                   d ,
    24                   e
    25                 )
    26                 SELECT  RAND() * 1000 ,
    27                         RAND() * 1000 ,
    28                         REPLICATE('a', 3) ,
    29                         @i ,
    30                         @i - 1;
    31         SELECT  @i = @i - 1;
    32     END; 
    33 --新建索引 (主键、非聚集索引)
    34 ALTER TABLE dbo.test ADD CONSTRAINT PK_test_id PRIMARY KEY(ID);
    35 CREATE INDEX IX_test_1 ON dbo.test(a);
    如下图,如果select *  因读取了abort_select_all字段(1/0)就会直接报错,从而达到不能直接select *的效果;
    直接按字段名查询没有问题(非abort_select_all字段)。
    非select *
    直接按字段名查询没有问题。

     
  • 相关阅读:
    About HDFS blocks
    Hadoop源代码分析(一)
    Hadoop源代码分析(三)
    MapReduce基础
    Pig安装与配置教程
    MapReduce数据流(三)
    MapReduce数据流(二)
    c++中的临时对象
    如何修改CMD命令行窗口下的默认路径
    VC2005: warning LNK4076: 无效的增量状态文件
  • 原文地址:https://www.cnblogs.com/jil-wen/p/6837245.html
Copyright © 2011-2022 走看看