【问题标题】:Does having multiple columns in a view vs lesser columns in Select in a view impacts performance?视图中有多个列与视图中的 Select 中的列较少会影响性能吗?
【发布时间】:2015-06-13 03:23:10
【问题描述】:

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

每当我查询 view 时,我总是查询 Name 和 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');

【问题讨论】:

  • 不要标记未涉及的产品。您在这里同时使用 MySQL 和 MS SQL Server 吗?
  • 在大多数情况下,性能是相同的。现代 SQL 引擎很容易处理这种情况。主要因素是适当的索引。
  • 优化器足够聪明,可以进行查询转换并使用最佳执行计划。因此,我认为这两种情况没有任何区别。

标签: mysql sql sql-server database oracle


【解决方案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>

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

案例#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>

案例#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>

所以,这两种情况下的解释计划是完全一样的。

【讨论】:

  • 您还可以使用 DBMS_Plan.Display(format => 'PROJECTION') 查看选择了哪些列。此外,在更高版本的 Oracle 中,如果这样做不影响输出基数并且不需要来自连接的数据,优化器将从查询中删除连接。
【解决方案2】:

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

例如,如果您的表上只有一个CLUSTERED 索引,并且您只有nameID 列,那么其他列也是read。根据其他列的类型,性能可能会受到显着影响。

现在,如果您像这样创建COVERING 非聚集索引:

CREATE INDEX IX_TEST ON [dbo].[TEST]
(
    [ID] ASC
   ,[Name] ASC
) 

如果您再次只查询IDname 列,SQL 查询引擎将使用它。这将以任何方式减少 IO 操作。多少,取决于表的大小和其他列的类型。

【讨论】:

  • 我不明白其他列将如何或为什么会被阅读???我对sql相当陌生,对此事没有深入的了解。您能否给我一些链接,以便我更好地了解此事。
  • SQL Server-sqlservercentral.com/stairway/72399查看这个系列关于索引的内容,你就会明白了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-22
  • 2023-02-03
  • 2010-10-06
  • 2010-11-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多