T-Sql

如何維護一個永遠執行的查詢?

  • May 13, 2021

我想執行一個查找素數的查詢,並且我想永遠執行它。

@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 &lt;= @endnumDividend.num between @startnum and @endnum
  • 一次生成 T16M 將允許您重複使用結果

    • 即:make是正則表

算法筆記

既然 SQL 語句定義了一個 RANGE……你可以執行 20 年

對於 A 和 B 之間的所有數字:

  1. 將它們分成更小、更易於管理的範圍。
  2. 並行執行 n 個塊

與分段篩法不同,您使用每個塊的所有值,而不僅僅是已知的素數。

分段篩

實施分段篩所需的更改

  • 關鍵是使用表 T16M 中的值,而不是 CTE。
  • 修改程式碼以刪除 T16M 中的非質數。(例如DELETE FROM T16M WHERE num in ( .... )
  • 以最低到最高的順序連續執行每個塊。

筆記

宇宙的壽命(以及所需的磁碟空間量)可能會限制你能找到多大的數字。

原始問題關注

  1. 長期執行系統

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

  1. 添加 CPU/RAM/磁碟

可以通過 SAN 系統添加/更換磁碟。

熱添加物理 CPU/RAM 可能需要非英特爾設備。

CPU 和記憶體資源可以無中斷地添加到系統中…… https://en.wikipedia.org/wiki/IBM_Z

分塊

Oracle 使用者可以使用它DMBS_PARALLEL_EXECUTE來創建塊並執行它們。其他 RDBMS 將需要實現自己的 API 來執行此操作。

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