Oracle

Oracle 簡單 count(*) SQL 查詢需要“永遠”

  • November 10, 2021

我在 Windows Server 2019 上新安裝 Oracle 12c 時遇到“問題”(​​至少是一種奇怪/緩慢的行為),此查詢至少需要 5 分鐘才能完成:

   SELECT COUNT(*) FROM SYS.ALL_VIEWS;

為什麼要花這麼多時間?我錯過了什麼?

Oracle 12c 在 SSD 上的 Win2019(在 VMWare VM 中)上執行。VM 有 5 GB 記憶體。對於“真實”數據庫來說,這可能還不夠,但我的數據庫包含一個預設的通用數據庫(沒有使用者數據),因為我只需要為客戶進行快速測試。

謝謝你。

SELECT COUNT(*) FROM SYS.ALL_VIEWS;

不是一個簡單的查詢。ALL_VIEWS是一個非常複雜的視圖,它有許多連接需要特殊的邏輯來確定呼叫使用者實際上可以看到什麼。

您可以使用all_views查看背後的邏輯all_views,這就是它在 19c 上的樣子。

select OWNER, VIEW_NAME, TEXT_LENGTH, TEXT, TEXT_VC,TYPE_TEXT_LENGTH, TYPE_TEXT,
      OID_TEXT_LENGTH, OID_TEXT, VIEW_TYPE_OWNER, VIEW_TYPE, SUPERVIEW_NAME,
      EDITIONING_VIEW, READ_ONLY,  CONTAINER_DATA, BEQUEATH,
      ORIGIN_CON_ID, DEFAULT_COLLATION, CONTAINERS_DEFAULT, CONTAINER_MAP,
      EXTENDED_DATA_LINK, EXTENDED_DATA_LINK_MAP, HAS_SENSITIVE_COLUMN
from int$dba_views
where (OWNER = SYS_CONTEXT('USERENV', 'CURRENT_USER')
      or OBJ_ID(OWNER, VIEW_NAME, 4, OBJECT_ID) in
           (select oa.obj#
            from sys.objauth$ oa
            where oa.grantee# in ( select kzsrorol
                                        from x$kzsro
                                 )
           )
       or /* user has system privileges */
          /* 4 is the type# for Views. See kgl.h for more info */
         exists (select null from v$enabledprivs
                 where priv_number in (-45 /* LOCK ANY TABLE */,
                                       -47 /* SELECT ANY TABLE */,
                                       -397/* READ ANY TABLE */,
                                       -48 /* INSERT ANY TABLE */,
                                       -49 /* UPDATE ANY TABLE */,
                                       -50 /* DELETE ANY TABLE */)
                 )
     )

夠簡單嗎?好吧,int$dba_views實際上是一個視圖本身,所以讓我們更深入一點,這個視圖定義為

select u.name, u.user#, o.name, o.obj#, o.type#, v.textlength, v.text,
      getlong(1, v.rowid),
      t.typetextlength, t.typetext,
      t.oidtextlength, t.oidtext, t.typeowner, t.typename,
      decode(bitand(v.property, 134217728), 134217728,
             (select sv.name from superobj$ h, sys."_CURRENT_EDITION_OBJ" sv
             where h.subobj# = o.obj# and h.superobj# = sv.obj#), null),
      decode(bitand(v.property, 32), 32, 'Y', 'N'),
      decode(bitand(v.property, 16384), 16384, 'Y', 'N'),

      decode(bitand(v.property/4294967296, 134217728), 134217728, 'Y', 'N'),
      decode(bitand(o.flags,8),8,'CURRENT_USER','DEFINER'),
      case when bitand(o.flags, (65536+131072+4294967296))>0 then 1 else 0 end,
      to_number(sys_context('USERENV', 'CON_ID')),
      nls_collation_name(nvl(o.dflcollid, 16382)),
      -- CONTAINERS_DEFAULT
      decode(bitand(v.property, power(2,72)), power(2,72), 'YES', 'NO'),
      -- CONTAINER_MAP
      decode(bitand(v.property, power(2,80)), power(2,80), 'YES', 'NO'),
      -- EXTENDED_DATA_LINK
      decode(bitand(v.property, power(2,52)), power(2,52), 'YES', 'NO'),
      -- EXTENDED_DATA_LINK_MAP
      decode(bitand(v.property, power(2,79)), power(2,79), 'YES', 'NO'),
      -- HAS_SENSITIVE_COLUMN
      decode(bitand(v.property, power(2,89)), power(2,89), 'YES', 'NO')
from sys."_CURRENT_EDITION_OBJ" o, sys.view$ v, sys.user$ u, sys.typed_view$ t
where o.obj# = v.obj#
 and o.obj# = t.obj#(+)
 and o.owner# = u.user#

猜猜看,sys."_CURRENT_EDITION_OBJ"也是一個具有復雜過濾器的視圖。我不會繼續粘貼,因為您可以在自己的 12c 安裝上跟踪跟踪(並且可能會略有不同)。

但是這裡要注意的重要一點是,ALL_VIEWS當您按名稱查找視圖時,實際使用速度很快,計算您可能能夠使用的每個視圖並不快(這是合理的,因為它不是您永遠需要匆忙做)。

如果您想ALL_VIEWS在某種基準測試中使用,那麼您可以將其具體化為一個表格併計算它。

create table all_views_mat as select * from all_views;

select count(*) from all_views_mat;

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