如何維護一個永遠執行的查詢?
我想執行一個查找素數的查詢,並且我想永遠執行它。
@Solomon Rutzky 在這個頁面上給定範圍內的素數,給我們一個關於埃拉托色尼篩的好例子。
DECLARE @RangeStart INT = 1, @RangeEnd INT = 100000; DECLARE @HowMany INT = CEILING((@RangeEnd - @RangeStart + 1) / 2.0); ;WITH frst AS ( SELECT tmp.thing1 FROM (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) tmp(thing1) ), scnd AS ( SELECT 0 AS [thing2] FROM frst t1 CROSS JOIN frst t2 CROSS JOIN frst t3 ), base AS ( SELECT TOP( CONVERT( INT, CEILING(SQRT(@RangeEnd)) ) ) ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [num] FROM scnd s1 CROSS JOIN scnd s2 ), nums AS ( SELECT TOP (@HowMany) (ROW_NUMBER() OVER (ORDER BY (SELECT 1)) * 2) + (@RangeStart - 1 - (@RangeStart%2)) AS [num] FROM base b1 CROSS JOIN base b2 ), divs AS ( SELECT [num] FROM base b3 WHERE b3.[num] > 4 AND b3.[num] % 2 <> 0 AND b3.[num] % 3 <> 0 ) SELECT given.[num] AS [Prime] FROM (VALUES (2), (3)) given(num) WHERE given.[num] >= @RangeStart UNION ALL SELECT n.[num] AS [Prime] FROM nums n WHERE n.[num] BETWEEN 5 AND @RangeEnd AND n.[num] % 3 <> 0 AND NOT EXISTS (SELECT * FROM divs d WHERE d.[num] <> n.[num] AND n.[num] % d.[num] = 0 );
所以我們可以很容易地生成一個從 0 到 100 的所有素數的列表。
但是假設我希望查詢在接下來的 20 年內執行,所以我設置了一個非常大的數字:
DECLARE @RangeStart INT = 1, @RangeEnd INT = 100000000000000000000000000000000000000000000000000;
**這就是問題所在:**我如何才能在接下來的 20 年內維護這個查詢?
因為埃拉托色尼篩法有一個特點:
如果它被中斷,你必須從頭開始。
所以我的問題從這裡開始:
- 我如何設法更換 CPU、升級 RAM、更換硬碟等…
- 如何管理故障轉移災難場景以避免該腳本停止?
- 故障轉移會保證查詢不會停止嗎?
- 雲冗餘和故障轉移到不同的提供商(Azure / AWS / GCE)這將確保腳本不會停止嗎?
- 如果故障轉移是從 Azure 到全球 2 個不同地區的 AWS 怎麼辦?此故障轉移會保持儲存過程執行嗎?
現在是災難恢復部分:
- 我可以備份,比如說每個月,該儲存過程的狀態,並最終從該映像恢復嗎?
- 如果我在虛擬機上執行儲存過程並拍攝快照,我可以恢復儲存過程嗎?
我確信有人在這樣做:這個分解素數的線上數據庫http://factordb.com/status.php已成功地從 200MB(2014 年)增加到今天(2019 年)的近 800MB。
第一個想法
你有一個 XY 問題。您需要使用允許您從特定點重新啟動的算法。
程式碼審查
Dividend.num <=@endnum
存在於兩個地方。
- 擺脫第二個
Divisor.num between 2 and sqrt(dividend.num) is more restrictive than
Divisor.num <= @endnum`。
- 擺脫限制較少的那個。
由於
NOT EXISTS
對所有行使用適當的行範圍Dividend
…
- 您可以安全地更改
Dividend.num <= @endnum
為Dividend.num between @startnum and @endnum
一次生成 T16M 將允許您重複使用結果
- 即:make是正則表
算法筆記
既然 SQL 語句定義了一個 RANGE……你可以執行 20 年
對於 A 和 B 之間的所有數字:
- 將它們分成更小、更易於管理的範圍。
- 並行執行 n 個塊
與分段篩法不同,您使用每個塊的所有值,而不僅僅是已知的素數。
分段篩
實施分段篩所需的更改
- 關鍵是使用表 T16M 中的值,而不是 CTE。
- 修改程式碼以刪除 T16M 中的非質數。(例如
DELETE FROM T16M WHERE num in ( .... )
)- 以最低到最高的順序連續執行每個塊。
筆記
宇宙的壽命(以及所需的磁碟空間量)可能會限制你能找到多大的數字。
原始問題關注
- 長期執行系統
Voyager 1/Voyager 2 是 40 年以來執行時間最長的電腦程序之一。
https://www.space.com/26041-nasa-voyager-probes-solar-system-legacy.html
航海者號為每個航天器使用三個雙冗餘電腦系統。 https://history.nasa.gov/computers/Ch6-2.html
- 添加 CPU/RAM/磁碟
可以通過 SAN 系統添加/更換磁碟。
熱添加物理 CPU/RAM 可能需要非英特爾設備。
CPU 和記憶體資源可以無中斷地添加到系統中…… https://en.wikipedia.org/wiki/IBM_Z
分塊
Oracle 使用者可以使用它
DMBS_PARALLEL_EXECUTE
來創建塊並執行它們。其他 RDBMS 將需要實現自己的 API 來執行此操作。