程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> 其他數據庫知識 >> MSSQL >> 依據sql劇本修正數據庫表構造的幾種處理計劃

依據sql劇本修正數據庫表構造的幾種處理計劃

編輯:MSSQL

依據sql劇本修正數據庫表構造的幾種處理計劃。本站提示廣大學習愛好者:(依據sql劇本修正數據庫表構造的幾種處理計劃)文章只能為提供參考,不一定能成為您想要的結果。以下是依據sql劇本修正數據庫表構造的幾種處理計劃正文


微線程范疇(至多在 Python 中)一向都是 Stackless Python 能力觸及的特別加強部門。關於 Stackless 的話題和比來它閱歷的變更,能夠自己就值得開拓一個專欄了。但個中簡略的事理就是,在“新的 Stackless”下,延續(continuation)明顯是不達時宜的,但微線程照樣這個項目 存在的來由。這一點很龐雜……

剛開端,我們照樣先往返顧一些內容。那末,甚麼是微線程呢? 微線程根本上可以說是只須要很少的外部資本便可以運轉的過程 ― 而且是在 Python 說明器的單個實例中(在公共內存空間中,等等)運轉的過程。有了微線程,我們便可能在今朝中等機能的 PC 機上運轉數以萬計的並行過程,還可以每秒鐘幾十萬次地在高低文之間切換。對 fork() 的挪用或尺度的 OS 線程挪用基本不克不及到達這個水平!乃至所謂的“輕量級”線程庫中的線程也比這裡提出的微線程“重”好幾個數目級。

我在本專欄中引見的簡便線程的寄義與 OS 線程的寄義有一點分歧。就這點而言,它們與 Stackless 所供給的也不盡雷同。在許多方面,簡便線程比年夜多半變體都簡略很多;年夜多半關於旌旗燈號、鎖定及諸如斯類的成績都不存在了。簡略性的價值就是,我提出了一種“協作多線程”的情勢;我認為在尺度 Python 框架中參加搶占其實不可行(至多在非 Stackless 的 Python 2.2 中 — 沒有人曉得 __future__ 會帶來甚麼)。

簡便線程在某種意義上會使人回憶起較早的 Windows 和 MacOS 版本的協作多義務(不外是在單個運用法式中)。但是,在另外一種意義上,簡便線程只不外是在法式中表達流的另外一種方法;簡便線程所做的一切(至多在准繩上)都可以用“真正宏大的 if/elif 塊”技巧來完成(蠻干的法式員的黔驢之計)。

一種用簡略的生成器模仿協同法式的機制。這個機制的焦點部門異常簡略。 scheduler() 函數中包裝了一組生成器對象,這個函數掌握將掌握流拜托給適合的分支的進程。這些協同法式其實不是 真實的協同法式,由於它們只掌握到 scheduler() 函數和來自該函數的分支。不外出於適用的目標,您可以用異常少的額定代碼來完成異樣的工作。 scheduler() 就是相似於上面如許的代碼:
清單 1. 模仿協同法式的 Scheduler()

def scheduler(gendct, start):
 global cargo
 coroutine = start
 while 1:
  (coroutine, cargo) = gendct[coroutine].next()

關於這個包裝器要留意的一點是,每一個生成器/協同法式都邑生成一個包括它的預期分支目的的元組。生成器/協同法式根本上都在 GOTO 目的處加入。為了便利起見,我還讓生成器生成了一個尺度的 cargo 容器,作為情勢化在協同法式之間傳送的數據的辦法 — 不外您也能夠只用曾經殺青分歧的全局變量或回調 setter/getter 函數來傳送數據。Raymond Hettinger 撰寫了一個 Python 加強建議(Python Enhancement Proposal,PEP),旨在使傳送的數據能被更好地封裝;能夠往後的 Python 將包含這個建議。

新的調劑法式

關於簡便線程來講,它們的需求與協同法式的需求稍有分歧。不外我們照樣可以在它的焦點處應用 scheduler() 函數。分歧的地方在於,調劑法式自己應當決議分支目的,而不是從生成器/協同法式吸收分支目的。上面讓我向您展現一個完全的測試法式和樣本:
清單 2. microthreads.py 示例劇本

from
  
   __future__ 
  
  import
  
   generators
  
  import
  
   sys, time
threads = []
TOTALSWITCHES = 
  
  10**6
NUMTHREADS = 
  
  10**5def
  
   null_factory():
 
  
  def
  
   empty():
  
  
  while1: 
  
  yield
  
   None
 
  
  return
  
   empty()
  
  def
  
   quitter():
 
  
  for
  
   n 
  
  in
  
   xrange(TOTALSWITCHES/NUMTHREADS):
  
  
  yield
  
   None
  
  def
  
   scheduler():
 
  
  global
  
   threads
 
  
  try
  
  :
  
  
  while1:
   
  
  for
  
   thread 
  
  in
  
   threads: thread.next()
 
  
  except
  
   StopIteration:
  
  
  passif
  
   __name__ == 
  
  "__main__"
  
  :
 
  
  for
  
   i 
  
  in
  
   range(NUMTHREADS):
  threads.append(null_factory())
 threads.append(quitter())
 starttime = time.clock()
 scheduler()
 
  
  print"TOTAL TIME: "
  
  , time.clock()-starttime
 
  
  print"TOTAL SWITCHES:"
  
  , TOTALSWITCHES
 
  
  print"TOTAL THREADS: "
  
  , NUMTHREADS

這年夜概就是您可以或許選擇的最簡略的簡便線程調劑法式了。每一個線程都按固定次序進入,並且每一個線程都有異樣的優先級。接上去,讓我們來看看若何處置細節成績。和後面部門所講的協同法式一樣,編寫簡便線程時應當遵照一些商定。

處置細節

年夜多半情形下,簡便線程的生成器都應當包含在 while 1: 輪回中。這裡設置調劑法式的辦法將招致在個中一個線程停滯時全部調劑法式停滯。這在某種意義上“硬朗性”不如 OS 線程 ― 不外在 scheduler() 的輪回 內捕捉異常不會比在輪回外須要更多的機械資本。並且,我們可以從 threads 列表刪除線程,而不用終止(由它自己或其它線程終止)。我們其實並沒有供給讓刪除加倍輕易的具體辦法;不外比擬經常使用的擴大辦法能夠是將線程存儲在字典或某種其它的構造中,而不是列表中。

該示例解釋了最初終止調劑法式輪回的一種公道的辦法。 quitter() 是一種特別的生成器/線程,它監督某種前提(在本示例中只是一個高低文切換的計數),並在前提知足時拋出 StopIteration (本示例中不捕捉其它異常)。請留意,在終止以後,其它一切生成器照樣完全的,假如須要,還可以在往後恢復(在微線程調劑法式或其它法式中)。明顯,假如須要,您可以 delete 這些生成器/線程。

這裡評論辯論的示例應用了特別的有意義線程。它們甚麼也不做,並且以一種能夠性最小的情勢完成這一點。我們如許樹立該示例是為了解釋一點 ― 簡便線程的內涵開支長短常低的。在一台比擬老的只要 64 MB 內存的 Windows 98 Pentium II 膝上型電腦上創立 100,000 個簡便線程是易如反掌的(假如到達了一百萬個線程,就會湧現長時光的磁盤“猛轉”)。請用 OS 線程嘗嘗看! 並且,在這個比擬慢的 366 MHz 芯片上可以在年夜約 10 秒內履行一百萬次高低文切換(所觸及的線程數對耗時並沒有嚴重影響)。明顯,真實的簡便線程應當 做一些工作,而這將依據義務應用更多的資本。不外線程自己卻博得了“簡便”的名聲。

切換開支

在簡便線程之間切換開支很小,但還不是完整沒有開支。為了測試這類情形,我構建了一個履行 某種任務(不外年夜約是您在線程中按事理可以完成的起碼量)的示例。由於線程調劑法式 真的同等於“履行 A,接著履行 B,然後履行 C,等等”的指令,所以要在主函數中創立一個完整並行的情形也不艱苦。
清單 3. overhead.py 示例劇本

from
  
   __future__ 
  
  import
  
   generators
  
  import
  
   time
TIMES = 100000
  
  def
  
   stringops():
 
  
  for
  
   n 
  
  in
  
   xrange(TIMES):
  s = 
  
  "Mary had a little lamb"
  
  
  s = s.upper()
  s = 
  
  "Mary had a little lamb"
  
  
  s = s.lower()
  s = 
  
  "Mary had a little lamb"
  
  
  s = s.replace('a','A')
  
  def
  
   scheduler():
 
  
  for
  
   n 
  
  in
  
   xrange(TIMES):
  
  
  for
  
   thread 
  
  in
  
   threads: thread.next()
  
  def
  
   upper():
 
  
  while1:
  s = 
  
  "Mary had a little lamb"
  
  
  s = s.upper()
  
  
  yield
  
   None
  
  def
  
   lower():
 
  
  while1:
  s = 
  
  "Mary had a little lamb"
  
  
  s = s.lower()
  
  
  yield
  
   None
  
  def
  
   replace():
 
  
  while1:
  s = 
  
  "Mary had a little lamb"
  
  
  s = s.replace(
  
  'a'
  
  ,
  
  'A'
  
  )
  
  
  yield
  
   None
  
  if
  
   __name__==
  
  '__main__':
  
  
 start = time.clock()
 stringops()
 looptime = time.clock()-start
 
  
  print"LOOP TIME:"
  
  , looptime
 
  
  global
  
   threads
 threads.append(upper())
 threads.append(lower())
 threads.append(replace())
 start = time.clock()
 scheduler()
 threadtime = time.clock()-start
 
  
  print"THREAD TIME:"
  
  , threadtime

成果注解,在直接輪回的版本運轉一次的時光內,簡便線程的版本運轉了兩次還多一點點 ― 也就相當於在下面提到的機械上,簡便線程運轉了不到 3 秒,而直接輪回運轉了跨越 6 秒。明顯,假如每一個任務單位都相當於單個字符串辦法挪用的兩倍、十倍或一百倍,那末所消費的線程開支比例就響應地更小了。

設計線程

簡便線程可以(並且平日應當)比零丁的概念性操作范圍更年夜。不管是何種線程,都是用來表現描寫一個特定 義務或 運動所需的流高低文的量。然則,義務消費的時光/年夜小能夠比我們願望在零丁線程高低文中應用的要多/年夜。搶占將主動處置這類成績,不須要運用法式開辟者作出任何特定干預。不幸的是,簡便線程用戶須要留意“好好地處置”其它線程。

至多,簡便線程應當設計得足夠周全,在完成概念性操作時應當可以或許 yield 。調劑法式將回到這裡以停止下一步。舉例來講:
清單 4. 偽碼友愛的簡便線程

def nicethread():
    while 1:
        ...operation A...
        yield None
        ...operation B...
        yield None
        ...operation C...
        yield None

多半情形下,好的設計將比在根本操作之間的界限 yield 更屢次。固然如斯,平日在概念上“根本”的器械都觸及對一個年夜聚集的輪回。假如情形如斯(依據輪回體消耗時光的水平),在輪回體中參加一到兩個 yield (能夠在特定命量的輪回迭代履行事後再次產生)能夠會有所贊助。和優先權線程的情形分歧,一個行動不良的簡便線程會獲得無窮量的獨有處置器時光。

調劑的其它部門

迄今為止,下面的示例只展現了情勢最根本的幾個線程調劑法式。能夠完成的還有許多(這個成績與設計一個好的生成器/線程沒甚麼關系)。讓我來趁便向您展現幾個傳送中能夠湧現的加強。
更好的線程治理

一個簡略的 threads 列表便可以使添加調劑法式要處置的生成器/線程異常輕易。然則這類數據構造其實不能使刪除或暫掛不再相干的線程變得輕易。字典或類能夠是線程治理中更好的數據構造。上面是一個快捷的示例,這個類可以或許(簡直可以或許)趁便拜訪示例中的 threads 列表:
清單 5. 線程治理的 Python 類示例

class
    
     ThreadPool: 
  
    
    """Enhanced threads list as class
  threads = ThreadPool()
  threads.append(threadfunc) # not generator object
  if threads.query(num) <<has some property>>:
    threads.remove(num)
  """def
    
     __init__(self):
    self.threadlist = []
    self.threaddict = {}
    self.avail = 
    
    1def
    
     __getitem__(self, n):
    
    
    return
    
     self.threadlist[n]
  
    
    def
    
     append(self, threadfunc, docstring=None):
    
    
    # Argument is the generator func, not the gen object
# Every threadfunc should contain a docstring
    
    
    docstring = docstring 
    
    or
    
     threadfunc.__doc__
    self.threaddict[self.avail] = (docstring, threadfunc())
    self.avail += 
    
    1
    self.threadlist = [p[
    
    1] 
    
    for
    
     p 
    
    in
    
     self.threaddict.values()]
    
    
    return
    
     self.avail-
    
    1# return the threadIDdef
    
     remove(self, threadID):
    
    
    del
    
     self.threaddict[threadID]
    self.threadlist = [p[
    
    1] 
    
    for
    
     p 
    
    in
    
     self.threaddict.values()]
  
    
    def
    
     query(self, threadID):
    
    
    "
    
    Information on thread, 
    
    if
    
     it exists (otherwise None)
    
    
    return
    
     self.threaddict.get(threadID,[None])[0]

您可以完成更多內容,而這是個好的終點。
線程優先級

在簡略的示例中,一切線程都取得調劑法式一致的存眷。至多有兩種通俗辦法可以完成調優水平更好的線程優先級體系。一個優先級體系可以只對“高優先級”線程投入比低優先級線程更多的留意力。我們可以用一種直接的方法完成它,就是創立一個新類 PriorityThreadPool(ThreadPool) ,這個類在線程迭代時代更頻仍地前往更主要的線程。最簡略的辦法能夠會在 .__getitem__() 辦法中持續屢次前往某些線程。那末,高優先級線程便可能吸收到兩個,或多個,或一百個持續的“時光片”,而不只是本來的一個。這裡的一個(異常弱的)“及時”變量最多能夠前往散落在線程列表中遍地的主要線程的多個正本。這將增長辦事於高優先級線程的現實頻率,而不只是它們遭到的一切存眷。

在純 Python 中應用更龐雜的線程優先級辦法能夠不是很輕易(不外它是應用某種第三方特定於 OS/處置器的庫來完成的)。調劑法式不是只給高優先級線程一個時光片的整型數,它還可以丈量每一個簡便線程中現實消費的時光,然後靜態調劑線程調劑,使其對期待處置的線程加倍“公正”(或許公正性和線程優先級是相干的)。不幸的是,Python 的 time.clock() 和它的系列都不是精度足夠高的計時器,缺乏以使這類方法有用。另外一方面,沒有甚麼可以阻攔“多時光片”辦法中處置缺乏的線程去靜態進步它本身的優先級。
將微線程和協作法式聯合在一路

為了創立一個簡便線程(微線程)調劑法式,我刪除協作法式邏輯“please branch to here”。如許做其實其實不需要。示例中的簡便線程生成的平日都是 None ,而不是跳轉目的。我們完整可以把這兩個概念聯合在一路:假如協同法式/線程生成了跳轉目的,調劑法式便可以跳轉到被要求的處所(或許,除非被線程優先級籠罩)。但是,假如協同法式/線程只生成 None ,調劑法式便可以本身決議下一步要存眷哪一個恰當的線程。決議(和編寫)一個隨意率性的跳轉畢竟會若何與線性線程隊列交互將觸及到很多任務,不外這些任務中沒有甚麼特殊奧秘的處所。

疾速而便宜 — 為何不愛好它呢?

微線程形式(或許“簡便線程”)根本上可以歸結為 Python 中流掌握的另外一種奇異的作風。本專欄的後面幾個部門曾經談到了別的幾種作風。有各類掌握機制的惹人的地方在於,它閃開發者將代碼功效性隔離在其邏輯組件內,並最年夜化代碼的高低文相干性。

其實,要完成做任何能夠做到的事的 能夠性其實不龐雜(只需用一個“loop”和一個“if”便可以了)。關於隨意馬虎地分化為許多渺小的“署理”、“辦事器”或“過程”的一類成績來講,簡便線程能夠是表達運用法式的底層“營業邏輯”的最清晰的模子。固然,簡便線程與一些年夜家更熟知的流機制比擬速度能夠異常快,就這點而言並沒有年夜礙。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved