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 *
    直接按字段名查询没有问题。

     
  • 相关阅读:
    php命令注入
    mysql事物
    安装php环境
    移除服务器缓存实例
    show user profile synchronization tools
    manual start user profile import
    JSON is undefined. Infopath Form People Picker in SharePoint 2013
    asp.net web 应用站点支持域账户登录
    Load sharepoint envirement by powershell
    sharepoint 2016 download
  • 原文地址:https://www.cnblogs.com/jil-wen/p/6837245.html
Copyright © 2011-2022 走看看