2017-11-18 104 views
0

有大數據的表,有人知道如何優化count語句嗎?例如:表預訂(ID,電子郵件,手機,...)(約30個字段)。Oracle - 在有大量數據的表上需要多次計數的建議

Function GetBookingCount(p_email, p_mobile) return number 
    Select count(id) 
    from Booking 
    Where email = p_email 
    or mobile = p_mobile 

Function GetBookingStatus3Count(p_email, p_mobile) return number 
    Select count(id) 
    from Booking 
    Where (email = p_email or mobile = p_mobile) 
    and status = 3; 

最終選擇:

Select GetBookingCount(email, mobile) as BookingCount 
     , GetBookingStatus3Count(email, mobile) as BookingStatus3Count 
     , ... 
From Booking 
where .... 

解決方法1:設置在WHERE子句中算作電子郵件列,移動,狀態欄什麼的字段列索引。

解決方案2:創建一個包含少量列的新表。 新表:Booking_Stats(id,電子郵件,手機,狀態)。

感謝您的任何建議。

回答

0

預訂表應該有一個關於電子郵件,手機和狀態的索引。你應該使用這個選擇:

WITH B1 AS 
(
    SELECT ID, 
      COUNT(ID) CNT1, 
      STATUS 
    FROM BOOKING 
    WHERE EMAIL = P_EMAIL 
      AND MOBILE = P_MOBILE 
) 
SELECT CNT1, 
     COUNT(ID) CNT2 
FROM B1 
WHERE STATUS = 3; 
+0

謝謝,但你的SQL可能是錯誤的,不工作,請參閱oracle中的sql – hungudgm

1
select count(*) count_all, count(case when status=3 then 1 else null end) count_status_3 
from Booking 
where email = p_email and mobile = p_mobile 

//注意:(電子郵件,移動查詢從頭寫的,沒有測試

你會考慮創建上(電子郵件,手機)或索引,狀態)取決於你得到的給定(電子郵件,移動設備)的行數,你將支付更新狀態改變索引的費用(如果允許的話)。如果同一行的狀態有很多更新,您可能更喜歡僅索引(電子郵件,手機)[讀/寫成本折衷]。

電子郵件很可能是非常區分的(一個值會過濾大部分列)。如果不是這種情況,請考慮將訂單更改爲(手機,電子郵件),如果移動列是更好的候選人。

+0

感謝您的詳細知識,但您的SQL也相同我的解決方案1 ​​ – hungudgm

+0

@hungudgm好吧,我沒有從問題中推論出來。那將是你情況最好的方式。 – igr

1

似乎所有這些功能都沒有幫助,實際上對性能無害。

您還沒有發佈一套完整的要求(什麼是...意思?),所以這是很難確定的,但它很可能是沿着這些路線的解決方案會更表演:

with bk as (
    select * 
    from booking 
    where email = p_email 
    or mobile = p_mobile 
) 
select count(*) as BookingCount 
     , count(case when bk.status = 3 then 1 end) as BookingStatus3Count 
     , ... 
from bk 

想法是查詢基表一次,獲取計算所有計數所需的所有數據,並在儘可能最小的結果集上計算聚合。

booking(email,mobile)上的索引可能有用,但可能不會。更好的解決方案是對p_emailp_mobile中的每一個都有不同的查詢,單列索引支持每個查詢。