在视图中选择多个列与视图中选择的较小列会影响性能吗?

时间:2015-04-08 08:52:32

标签: mysql sql sql-server database oracle

我有一个customer_view,其中有6个字段 ID , Name , Email , First_Name , Last_Name , Status

每当我查询视图时,我总是查询名称和ID。

我是否应该仅使用字段ID和名称创建另一个自定义视图Customer_Custom_view?

这会以任何方式影响表现吗?

Select Id from users
where customer_id = (select id from customer_view where name ='XYZ');

Select Id from users
where customer_id = (select id from customer_custom_view where name = 'XYZ');

2 个答案:

答案 0 :(得分:1)

我认为 Oracle优化器非常智能,可以转换查询并在两种情况下都使用最佳执行计划。因此,很可能根本没有任何区别。

为什么不测试它看看。


基表上没有索引

案例#1 现有观点

SQL> CREATE OR REPLACE VIEW emp_view AS SELECT empno, ename, deptno, JOB, sal, mgr FROM emp;

View created.

SQL>
SQL> EXPLAIN PLAN FOR
  2  SELECT * FROM emp
  3  where empno = (select empno from emp_view where ename='SCOTT');

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 587534197

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |    37 |     6   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL | EMP  |     1 |    37 |     3   (0)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL| EMP  |     1 |    10 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------

   1 - filter("EMPNO"= (SELECT "EMPNO" FROM LALIT."EMP" "EMP" WHERE
              "ENAME"='SCOTT'))
   2 - filter("ENAME"='SCOTT')

16 rows selected.

SQL>

案例#2 自定义视图

SQL> CREATE OR REPLACE VIEW emp_custom_view AS SELECT empno, ename FROM emp;

View created.

SQL>
SQL> EXPLAIN PLAN FOR
  2  SELECT * FROM emp
  3  WHERE empno = (SELECT empno FROM emp_custom_view WHERE ename='SCOTT');

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 587534197

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |    37 |     6   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL | EMP  |     1 |    37 |     3   (0)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL| EMP  |     1 |    10 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------

   1 - filter("EMPNO"= (SELECT "EMPNO" FROM LALIT."EMP" "EMP" WHERE
              "ENAME"='SCOTT'))
   2 - filter("ENAME"='SCOTT')

16 rows selected.

SQL>

使用基表上的索引,并使用过滤谓词中的索引列

CASE#1现有视图

SQL> CREATE OR REPLACE VIEW emp_view AS SELECT empno, ename, deptno, JOB, sal, mgr FROM emp;

View created.

SQL>
SQL> EXPLAIN PLAN FOR
  2  SELECT * FROM emp
  3  where empno = (select empno from emp_view where empno= 7369);

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------
Plan hash value: 4162864836

--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     1 |    39 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |    39 |     1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | PK_EMP |     1 |       |     0   (0)| 00:00:01 |
|*  3 |    INDEX UNIQUE SCAN        | PK_EMP |     1 |     4 |     0   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("EMPNO"= (SELECT "EMPNO" FROM SCOTT."EMP" "EMP" WHERE
              "EMPNO"=7369))
   3 - access("EMPNO"=7369)

17 rows selected.

SQL>

CASE#2自定义视图

SQL> CREATE OR REPLACE VIEW emp_custom_view AS SELECT empno, ename FROM emp;

View created.

SQL>
SQL> EXPLAIN PLAN FOR
  2  SELECT * FROM emp
  3  WHERE empno = (SELECT empno FROM emp_custom_view WHERE empno=7369);

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------
Plan hash value: 4162864836

--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     1 |    39 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |    39 |     1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | PK_EMP |     1 |       |     0   (0)| 00:00:01 |
|*  3 |    INDEX UNIQUE SCAN        | PK_EMP |     1 |     4 |     0   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("EMPNO"= (SELECT "EMPNO" FROM SCOTT."EMP" "EMP" WHERE
              "EMPNO"=7369))
   3 - access("EMPNO"=7369)

17 rows selected.

SQL>

因此,两种情况下的解释计划完全相同。

答案 1 :(得分:0)

根据在基础表上创建的索引,可能会有很大差异。

例如,如果您的桌面上只有CLUSTERED索引,并且querying只有nameID列,则其他列为{{1}也是。根据其他列的类型,性能可以大幅提升。

现在,如果您创建一个read非聚集索引,如下所示:

COVERING

并且您只查询CREATE INDEX IX_TEST ON [dbo].[TEST] ( [ID] ASC ,[Name] ASC ) ID列,SQL查询引擎将使用它。这将以任何方式减少IO操作。多少,取决于您的表的大小和其他列的类型。