Oracle

查看:如果不使用左連接,則忽略它?

  • December 19, 2019

我有一個 Web 服務,它引用了一個名為gis_sidewalks_vw.

create table gis_sidewalks (
   id number(10,0),
   last_edited_date date
   );
insert into gis_sidewalks (id, last_edited_date) values (1, TO_DATE('2019/01/01 00:00:00', 'yyyy/mm/dd hh24:mi:ss'));
insert into gis_sidewalks (id, last_edited_date) values (2, TO_DATE('2019/02/01 00:00:00', 'yyyy/mm/dd hh24:mi:ss'));
insert into gis_sidewalks (id, last_edited_date) values (3, TO_DATE('2019/03/01 00:00:00', 'yyyy/mm/dd hh24:mi:ss'));
insert into gis_sidewalks (id, last_edited_date) values (4, TO_DATE('2019/04/01 00:00:00', 'yyyy/mm/dd hh24:mi:ss'));
commit;

create table maximo_assets (
   id number(10,0),
   lastsyncdate date
   );
insert into maximo_assets (id, lastsyncdate) values (1, TO_DATE('2019/04/01 00:00:00', 'yyyy/mm/dd hh24:mi:ss'));
insert into maximo_assets (id, lastsyncdate) values (2, TO_DATE('2019/03/01 00:00:00', 'yyyy/mm/dd hh24:mi:ss'));
insert into maximo_assets (id, lastsyncdate) values (3, TO_DATE('2019/02/01 00:00:00', 'yyyy/mm/dd hh24:mi:ss'));
insert into maximo_assets (id, lastsyncdate) values (4, TO_DATE('2019/01/01 00:00:00', 'yyyy/mm/dd hh24:mi:ss'));
commit;

create or replace view gis_sidewalks_vw as (
select
   s.id,
   s.last_edited_date as gis_last_edited_date,
   a.lastsyncdate as maximo_lastsyncdate,
   case 
       when s.last_edited_date > a.lastsyncdate then 1
   end sync_needed
from
   gis_sidewalks s
left join
   maximo_assets a
   on s.id = a.id
);

select * from gis_sidewalks_vw;

        ID GIS_LAST_EDITED_DATE MAXIMO_LASTSYNCDATE SYNC_NEEDED
---------- -------------------- ------------------- -----------
         1 01-JAN-19            01-APR-19                      
         2 01-FEB-19            01-MAR-19                      
         3 01-MAR-19            01-FEB-19                     1
         4 01-APR-19            01-JAN-19                     1

該視圖有一個左連接和一個計算列

case 
   when s.last_edited_date > a.lastsyncdate then 1
end sync_needed

...

left join
   maximo_assets a

設想:

視圖和網路服務是多用途的

目的#1:

提供cron任務所在的行sync_needed = 1(每周同步到單獨的數據庫)。

目的#2:

將視圖中的所有行提供給 web 地圖(地圖一直在使用)。


問題:

maximo_assets在目的 #1 中,加入表並生成計算列是有意義的。

但是,在目的 #2 中,加入表並生成計算列是沒有意義的。maximo_assets

不出所料,出於目的 #2,由於不必要的加入,我在 web 地圖中遇到了性能問題。


問題:

有沒有辦法設計視圖,以便在未使用連接時忽略maximo_assets表的連接?

例如:

select
   id,
   gis_last_edited_date
   --maximo_lastsyncdate
   --sync_needed
from
   gis_sidewalks_vw

在此處輸入圖像描述

想想看。這種沒有進一步資訊的連接不能被跳過。即使您不從 maximo_assets 中選擇列,與其連接也可能會增加返回的行數,因為對於 gis_sidewalks 中的 1 個 ID,您可以在 maximo_assets 中擁有多個具有相同 ID 的行。

如果 ID 是唯一的(或 PK),並且您通過創建適當的約束使數據庫知道這一點,那麼上述情況不再適用,它將能夠跳過 maximo_assets 表:

alter table gis_sidewalks add primary key (id);
alter table maximo_assets add primary key (id);

select
   id,
   gis_last_edited_date--,
   --maximo_lastsyncdate,
   --sync_needed
from
   gis_sidewalks_vw;

       ID GIS_LAST_
---------- ---------
        1 01-JAN-19
        2 01-FEB-19
        3 01-MAR-19
        4 01-APR-19

SQL> select * from table(dbms_xplan.display_cursor);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  f4p3b2huhfk5a, child number 0
-------------------------------------
select     id,     gis_last_edited_date--,     --maximo_lastsyncdate,
 --sync_needed from     gis_sidewalks_vw

Plan hash value: 1031306697

-----------------------------------------------------------------------------------
| Id  | Operation         | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |               |       |       |     3 (100)|          |
|   1 |  TABLE ACCESS FULL| GIS_SIDEWALKS |     4 |    88 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------------

Note
-----
  - dynamic statistics used: dynamic sampling (level=2)

您發布的子查詢的性能不會很好地擴展。

此外,多用途 SQL 是許多性能問題的根源,因此請小心處理。

引用自:https://dba.stackexchange.com/questions/249862