如何對從水平分區表中獲取的數據進行排序
我有一個電信計費軟體系統。其中有使用者通話的每日日誌。日誌按日期(月)水平分區。每個分區都儲存在一個單獨的數據庫中,並且可以分佈在多個實例中。
在 UI 中,使用者將指定一個日期範圍。返回的數據可以按任何欄位排序。日期範圍可能跨越多個分區。應用程序必須支持對日期範圍的數據進行分頁。
我無法將太多記錄載入到記憶體中進行排序。將排序放在查詢中只會給我一個結果集中的排序數據。
所以我需要對來自多個分區的數據進行排序,每個分區都單獨排序。如何從多個排序結果集中將排序記錄返回到 UI?
通過依靠 ResultSet 在記憶體中載入有限數據的能力,我們能夠使用動態比較器在 Java 中提出解決方案。解決方案是從每個 resultSet 中獲取第一條記錄並在 java 中對其進行排序,然後從排序的數據中返回第一個元素。
詳細解決方案:
首先,我們建構了一個程序,它可以根據螢幕上選擇的標準為我們提供一個動態比較器。
其次,我們在 DAO 上編寫了一個 AggregateResultSet 包裝器,它包裝了來自不同分區的 ResultSet。注意:這些單獨的 ResultSet 已經按照相同的標准進行了排序。然後 AggregateResultSet 將被賦予一個動態比較器。
這個 AggregateResultSet 將有一個資料結構來儲存每個結果集的第一個元素。它將在呼叫 next() 時返回下一個元素。此元素將是根據 dynamicComparator 最先出現的元素。在 next() 呼叫期間,我們從臨時資料結構中刪除該元素,並將同一結果集中的下一個元素插入到臨時資料結構中。這樣,AggregateResultSet 將通過在 Java 中合併/儲存/排序非常有限的數據,以預期的順序返回數據。
我們希望沒有比較問題,因為我們在排序中主要是數字/字元串數據。
聽起來您的架構已經超越了分區並被分片。如果您有可以處理分片的系統軟體或應用程序框架,那麼應該實現此要求。
為了獲得正確的排序順序,您必須同時將所有相關分片的結果放在同一個地方。沒有辦法從一個分片獲得一些結果,然後從另一個分片獲得更多結果,並且能夠保證使用者可以選擇的任何排序順序。
一種方法(正如 BriteSponge 建議的那樣)是定義一個跨越所有分片的視圖。讓 DBMS 處理編組各種分片結果集的複雜性。如果可以管理,這將是我的首選解決方案。它將應用程序與數據庫實現細節分開。
如果你必須自己寫這個,那麼你有分頁的事實是有希望的。這限制了您將在 UI 中顯示的最大行數,因此限制了必須從每個分片返回的最大行數。從日期範圍中,您可以確定需要哪些分片。向每個分片送出表單查詢
select <columns> from <table> where date between <start> and <end> order by <user selection> fetch first <number> rows only
這
<number>
將是您希望在 UI 的單個頁面中顯示的最大行數。雖然它們不太可能都來自一個分片,但這是可能的,所以這就是限制。如果您的 Oracle 版本不支持最終限制條款,則以下內容仍然有效,但效率會低得多。
對結果集執行多路合併。當您達到 UI 中一頁的限制時停止。丟棄剩餘的結果集。
當使用者向前尋呼時,使用標準尋呼技術重新送出 SELECT。
當使用者選擇不同的排序順序時,修改 SQL 以匹配並重新送出到每個分片。
我的偏好是在儲存過程中實現這個伺服器端。這將使應用程序和儲存盡可能分開。此外,與多路合併不同,各種結果集都可以進入一個工作表,然後對其進行排序並將正確數量的行返回給應用程序。
如果您確實在客戶端實現它,而不是丟棄結果集中未使用的部分,它們可以被記憶體。這可能會以額外的複雜性為代價來減少後續頁面的負載。