SQL中使用WITH AS提高效能

2021-06-09 04:19:04 字數 3150 閱讀 4765

1. 案例起因公司門店應用程式每天都要出乙份報表,用來統計所有商品當天的期初庫存數量、入庫數量、出庫數量

及當天的期末庫存數量。執行半年以後,這份報表執行越來越慢,到現在,每次執行該報表顯示當天資料時需要近20秒的時間。於是開發人員找到我,希望我看看,是不是可以使該報表執行的時間更短。

該報表就是一段sql語句,主要由三部分組成,第一部分是計算每個商品的期初數量,第二部分是計算每個商品的當天發生(包括入庫和出庫的)數量,第三部分是計算每個商品的期末數量,也就是當天的餘額。每個部分使用union all連線起來。

我看到該報表,第乙個感覺就是這段sql裡的每個部分都要對錶進行掃瞄,明顯成本過高。應該可以使用with as進行改寫。

2. with as的含義

with as短語,也叫做子查詢部分(subquery factoring),可以讓你做很多事情,定義乙個sql片斷,該sql片斷會被整個sql語句所用到。有的時候,是為了讓sql語句的可讀性更高些,也有可能是在union all的不同部分,作為提供資料的部分。

特別對於union all比較有用。因為union all的每個部分可能相同,但是如果每個部分都去執行一遍的話,則成本太高,所以可以使用with as短語,則只要執行一遍即可。如果with as短語所定義的表名被呼叫兩次以上,則優化器會自動將with as短語所獲取的資料放入乙個temp表裡,如果只是被呼叫一次,則不會。而提示materialize則是強制將with as短語裡的資料放入乙個全域性臨時表裡。很多查詢通過這種方法都可以提高速度。

3. 案例說明

首先介紹該sql所涉及到的主要的表的結構。該表表名為fin,用來存放每天每個商品的發生數以及該商

品的餘額數。其表結構為如下所示(這裡我只選取了與我們要討論的sql相關的部分表字段)。

sql> desc fin

名稱 是否為空? 型別

day date

sku varchar2(8)

inqty number(16,6)

outqty number(16,6)

lastqty number(16,6)

簡單解釋一下各個欄位的含義:

1) day:發生的日期。

2) sku:發生交易的商品**。

3) inqty:商品入庫數量。

4) outqty:商品出庫數量。

5) lastqty:商品的餘額數量。

該表中含有的記錄數量為:

sql> select count(*) from fin;

count(*)

select

sku,

sum(initqty) as initqty,

sum(inqty) as inqty,sum(outqty) as outqty,

sum(lastqty) as lastqty

from (

select sku,lastqty as initqty,0 as inqty,0 as outqty,0 as lastqty

from fin

where day=to_date('20030713','yyyymmdd')

union all

select sku,0 as initqty,inqty,outqty,0 as lastqty

from fin

where day>=to_date('20030714','yyyymmdd') and day<=to_date('20030714','yyyymmdd')

union all

select sku,0 as initqty,0 as inqty,0 as outqty,lastqty

from fin

where day=to_date('20030714','yyyymmdd')

group by sku;

我們來看該sql所花費的時間為:

sql> set timing on

sql> /

sku initqty inqty outqty lastqty

00106162 0 0 12 60

00106467 0 20 10 60

已選擇956行。

然後,我們來對該sql進行改寫一番,如下所示:

with result as (

select /*+ materialize */ day,sku,inqty,outqty,lastqty

from fin

where day>=to_date('20030713','yyyymmdd') and day<=to_date('20030714','yyyymmdd'))

select

sku,

sum(initqty) as initqty,

sum(inqty) as inqty,

sum(outqty) as outqty,

sum(lastqty) as lastqty

from (

select sku,lastqty as initqty,0 as inqty,0 as outqty,0 as lastqty

from result

where day=to_date('20030713','yyyymmdd')

union all

select sku,0 as initqty,inqty,outqty,0 as lastqty

from result

where day=to_date('20030714','yyyymmdd')

union all

select sku,0 as initqty,0 as inqty,0 as outqty,lastqty

from result

where day=to_date('20030714','yyyymmdd')

group by sku;

我們來看修改後的sql所花費的時間為:

sql> set timing on

sql> /

sku initqty inqty outqty lastqty

00106162 0 0 12 60

00106467 0 20 10 60

已選擇956行。

從這裡可以看到,通過with as可以從20秒降低到6秒,幾乎提高了65%的效能。

SQL中使用WITH AS提高效能

本文內容一部分來自 一 with as的含義 with as短語,也叫做子查詢部分 subquery factoring 可以讓你做很多事情,定義乙個sql片斷,該sql片斷會被整個sql語句所用到。有的時候,是為了讓sql語句的可讀性更高些,也有可能是在union all的不同部分,作為提供資料的...

SQL 中使用 WITH AS 提高效能

一 with as的含義 with as短語,也叫做子查詢部分 subquery factoring 可以讓你做很多事情,定義乙個sql片斷,該sql片斷會被整個sql語句所用到。有的時候,是為了讓sql語句的可讀性更高些,也有可能是在union all的不同部分,作為提供資料的部分。特別對於uni...

使用WITH AS提高效能簡化巢狀SQL

特別對於union all比較有用。因為union all的每個部分可能相同,但是如果每個部分都去執行一遍的話,則成本太高,所以可以使用with as短語,則只要執行一遍即可。如果with as短語所定義的表名被呼叫兩次以上,則優化器會自動將 with as短語所獲取的資料放入乙個temp表裡,如果...