← 全部概念地圖
標準

概念地圖・倒排索引

分類:系統

這一頁不只是把一個概念解釋一遍——一張自己畫的結構圖,加上拿台灣情境從頭走一次的實例演練、這個框架什麼時候會騙你,以及它接回 P.A.I.N. 之後長什麼樣。一頁必須交付的三層 →

倒排索引:先替每個詞備好一份名單

三千張工令堆在桌上,問題只有一句:這半年,哪幾張用過那一款閥?從第一張翻到最後一張,是最直覺的做法,也是最貴的做法。倒排索引把這件事整個翻面——事先替每一個詞,記住它出現在哪幾份文件;查詢那一刻就只剩讀名單、對名單。這張圖畫的是它的兩個零件:一疊排好序的詞典,加上每個詞後面掛著的一條過帳串列。下半張再示範兩條串列怎麼靠兩個指標,走一趟就把交集掃出來。

倒排索引:詞典、過帳串列,以及兩條串列取交集 圖分上下兩區。上區左欄是一疊已排序的詞典方塊,五個料號各自往右拉出一條過帳串列,串列裡是由小到大的文件編號,「閥」那一條最長,掛了五個編號。下區把「閥」與「幫浦」兩條串列上下對齊排開,左端各有一個朱紅三角指標,兩個指標各自往右走;編號 7 與 12 同時出現在兩排,各用一個金色外框圈住,那兩個就是交集。 每個詞先記一條名單,兩條名單再對著走 詞典(已排序) 過帳串列:該詞出現過的文件編號,由小到大 法蘭 軸承 閥 墊片 幫浦 3 12 18 18 25 30 3 7 12 18 25 5 7 7 12 30 金框這兩條,就是下面拿來取交集的那兩條 取交集:「閥」與「幫浦」上下對齊,兩個指標各自往右走,同號才收下 閥 幫浦 3 7 12 18 25 7 12 30 兩條名單合計 8 個編號,指標一路往前走,比對 5 次就掃完(最壞情況的上限是 7 次)
兩條名單上下對齊,指標往右走五次,交集就掉出來。

詞典與過帳串列,兩邊各存什麼

倒排索引只有兩個零件,卻常常被混成一個。拆開來看,各自存什麼、各自要付什麼,界線就清楚了。

零件裡面存什麼它在查詢裡的角色與代價
詞典資料裡出現過的每一個詞,各一筆,排好序拿一個詞進來,定位到那條名單的開頭
過帳串列該詞出現過的文件編號,由小到大排好從頭往右掃,掃到底就結束,不必回頭
取交集什麼都不另外存兩條名單各派一個指標,數字小的那邊先走一步
新增一份文件要寫進去的地方不只一處文件用到幾個詞,就得在幾條名單尾巴各補一筆

表裡最容易被跳過的是最後一列。前三列都在講「查的時候有多省」,最後一列才是這個結構真正的帳單——省下來的翻閱工,被搬到每一次寫入。招牌圖上半部那五條名單看起來是靜態的擺設,實際上它們每天都在變長;而變長這件事沒有人會替你自動做。

哪一種查詢值得建這份索引

一、這個問題會被問第幾次。船廠那位師傅要是一年只查一次「哪幾張工令用過 A38 型閥」,那把三千張翻完反而划算——建詞典的工,比翻一次還多。真正讓索引回本的,是同一句問法每個月都有人來問:品保要查、報價要查、客訴進來又要查一次。名單建一次,之後每一次查詢都在吃那一次的紅利。自問:同一類問題,上個月被問了幾次?

二、名單多久要跟著改一次。工令一天進二十張,每一張都要拆出料號、在對應的名單尾巴各補一筆——那是二十次寫入乘上每張用到的料號數。資料越動,這份名單就越像一個要天天餵的東西。反過來說,已經結案封存的那半年工令不會再變,替它建的索引一次做好就能放著用很久。自問:這份資料一天要改幾筆?

三、一次要同時卡住幾個條件。單一條件其實用不太到這個結構的好處。它真正發力的地方是「A38 型閥」和「不鏽鋼法蘭」要同時成立——兩條已經排好序的名單並排,兩個指標往右走一趟,答案就出來了,中間完全沒有回頭。條件越多,這種走法省下來的比對就越可觀。自問:一次查詢裡,要同時成立的條件有幾個?

四、拿到編號之後還要做什麼。名單吐出來的是文件編號,不是文件本身。船廠那邊真正要的常常是工令上的施工照片和簽核紀錄——那還得再開九份原始檔。若每次查完都得把命中的文件整份讀過,而命中的量又不小,索引省下的那一段就會被後面這一段吃掉一部分。自問:拿到編號之後,還得再開幾份原始檔?

三千張工令,反過來建一次

底下這家台灣南部的船舶修造廠,是為了把這個結構講清楚而編出來的示意情境,沒有指涉任何真實公司。

實例演練
  • 先數清楚要翻多少:半年 3000 張工令,全躺在同一個資料夾裡,誰都知道答案在裡面,就是沒人翻得完。翻到下班
  • 把工令反過來拆:逐張抽出用到的料號,湊出一本 1850 個料號的詞典——這是一次性的工,做完就不必再做。一次就好
  • 每個料號掛一條名單:「A38 型閥」後面掛 46 個工令編號,「不鏽鋼法蘭」後面掛 210 個,全部由小排到大。排好才好走
  • 兩條名單對著走:兩個指標各自往右,同號才收下,最後掉出 9 張工令。合計只讀了 256 筆編號,最壞情況也只比對 255 次。9 張看得完
  • 代價轉到寫入那一端:之後每進一張新工令,它用到幾個料號,就得在幾條名單尾巴各補一筆。漏補沒人知

值得記住的接縫在最後一步。前四步是一段很漂亮的曲線——一邊是 3000 張工令要一張張翻開,一邊是 256 筆編號讀過去就結束,中間隔著一本 1850 個料號的詞典。但那本詞典不是做完就能忘的東西:它每天要跟著現場長。真正會出事的地方在於,補名單的人和查名單的人,往往不是同一群人。查的人享受五次比對就出答案的爽快,補的人只覺得多了一道手續,而漏補的那一筆,要等三個月後有人查不到才會浮出來。這個結構把「慢」從查詢那一端搬到寫入那一端,搬得很成功,也搬得很安靜。以上為說明結構用的示意情境,僅供理解框架之用。

這份索引什麼時候會騙你

  1. 它只記得「出現過」。名單裡的編號,代表那個詞在那份文件裡出現過——至於這個料號是整張工令的主角,還是備註欄裡順手抄的一行,名單一個字都沒存。船廠拿到 9 張交集工令,很容易當成「這 9 張都在處理閥和法蘭的介面問題」,實際上可能有三張只是材料清單裡剛好同時列到。要判斷輕重,還得回去讀原文。
  2. 詞怎麼切,決定了你查不查得到。「A38 型閥」「A38型閥」「閥 A38」在詞典裡是三筆不同的東西——中間差的只是一個空白和一個順序。現場登錄時每個人的寫法不一樣,同義詞、簡寫、錯字也全都各佔一格。索引不會告訴你這件事,它只會誠實地回答「你問的那個詞,我這裡有這幾筆」,然後讓你以為那就是全部。
  3. 查不到的東西不會舉手。翻三千張工令雖然慢,但漏掉的那幾張你翻過就會有印象;名單查詢是乾淨的一刀,你只看得到它交出來的 9 張,看不到那些因為沒被建進詞典、或名單漏補而永遠不會出現的工令。錯誤在這裡是無聲的——它不報錯,它只是少給你幾筆,而少的那幾筆常常正是最該看的。

痛點視角:更新那一刻

痛點視角

這個結構把力氣挪去了寫入那一端。

查詢那一刻確實很漂亮——兩個指標往右走五次,答案就掉出來。漂亮是因為代價早就在別的時間點付掉了:每一張工令進系統的時候,得有人替它用到的每一個料號,在名單尾巴各補一筆。而那筆維護費會一路滑到最忙、最沒空、最容易分心的那個環節——現場登錄的那一刻。P.A.I.N. 裡的 A 問的正是這件事:誰真的動手?他做這一步有沒有回報?做漏了誰會發現?這張圖畫得出每個料號後面掛著幾筆編號,畫不出那個補編號的人今天已經加班到幾點。索引失準的原因多半藏在趕工那一天,有人跳過了那一步,而跳過的成本要三個月後才有人撞見。今晚可以做的一件事:翻出你系統裡「新增一筆資料」的操作流程,數一數它要順手更新幾張表。數字大於三,那條路遲早會有人抄近路。

常見問題

倒排索引跟一般資料庫索引有什麼差別?

形式上很像,用途不同。一般索引通常對一個欄位建,一筆資料在那個欄位上只有一個值;倒排索引處理的是「一份文件裡有很多個詞」這種一對多的關係,所以同一份文件會同時出現在好幾條名單裡。也因此它天生擅長多條件交集:把幾條名單並排走一趟就好。代價是同一份文件被寫進索引的次數,等於它用到的詞數。

過帳串列為什麼一定要由小到大排?

因為排序讓兩個指標可以只往前、不回頭。當左邊指到 3、右邊指到 7,你確定 3 不可能出現在右邊剩下的部分,所以左邊直接往前一格,右邊完全不動。少了排序,這個判斷就不成立,兩條名單只能兩兩比對,走法整個變回暴力。圖上那 5 次比對之所以夠用,全靠這個前提。

文件很少的時候還要不要建?

通常不必。建索引要先把每份文件拆一遍詞,那個成本跟文件量成正比,等於先付一次全掃的錢。文件只有幾十份、而且問題一年只問一次,直接掃反而快,也省掉往後所有的維護。判斷點在重複次數和更新頻率——資料量會長、問法會重複出現,那個門檻就會自己跨過去。

兩條名單長度差很多時要怎麼走?

從短的那條主導。46 筆和 210 筆並排時,逐個拿短名單的編號去長名單裡跳著找,往往比兩邊各走一步更省——因為長名單裡大段的編號根本不可能命中。實務上的做法是先按名單長度排序,最短的先交集,把候選集合壓小之後再接下一條。這也是為什麼很多實作會順手把每條名單的長度存起來。

把手邊那份查詢清單反過來寫一次,看它要記幾條名單。名單一多,下一個問題就變成「這些名單自己該怎麼排、怎麼找」——照鍵排序的樹狀索引處理的正是那一段;若你要確認的是兩邊的名單有沒有被人動過手腳,用雜湊比對整棵樹的做法是另一條路。

發現引用或事實有誤?請寫信回報,我會依更正政策修正。