透過假設來工作

如何在資訊殘缺的條件下,順利展開工作

Laurence Chen
Feb 20, 2023
working at the conditions that information is not enough

最近遇到了兩個題目,都算是需要利用假設才能有效進行的工作。

題目一:效能改進

客戶的軟體在報表產生的部分相當地慢,跑一個報表在資料量大的時候居然會需要一分鐘以上,客戶認為,這應該要考慮做程式碼的效能改進。客戶的軟體工程師認為,生成報表的程式碼最大的不同之處,就是有大量的資料轉換 (transformation),由於開發的程式語言是 Clojure ,會有比較多的資料拷貝,他們認為也許改成用一種節省資料拷貝的寫法 (Transducer) 會有幫助?

而我在第一時間就在心裡否定了這個假設。我的假設是:「十之八九會是資料庫的查詢問題。」有了假設還不夠,要驗証才行。我拿了 profiler 量測之後,得到了兩個結果:

  1. 報表產生的這段程式碼,它是 IO bound 而非 CPU bound 。換言之,它的時間主要消耗在 IO 而非 CPU 上。
  2. 某兩個查詢加起來,佔用了 95% 以上的時間。

由上述的兩個結果算是驗証了我的假設無誤。而 2 這點滿好的,因為根據阿姆達爾定律 (Amdahl’s law),效能瓶頸高度集中的話,很有機會只改進瓶頸就對整段程式碼得到極大的改進。接下來的第二個假設,則是我的前輩同事的真知卓見了,他認為,「儘管客戶使用的資料庫是 Datomic ,凡是身處於迴圈內的資料庫查詢,都有可能是瓶頸。」

照 Datomic 官方的說法,Datomic 不會有 N+1 問題,因為 Datomic 會把資料做大量的快取,於是查詢的效能會像是在本地端做的一樣,不太會受到 IO 的影響。而 N+1 問題是指:『如果把對資料庫的查詢寫在迴圈裡,由於資料庫的查詢需要做 IO ,這樣子很容易變得太慢。』確實,客戶的程式碼裡,迴圈裡有很多的對資料庫的查詢都沒有成為效能瓶頸,然而,成為效能瓶頸的查詢,它本身做了相當多的 join ,就是這些帶有大量 join 的查詢造成了效能問題,它們造成的 IO 實在太多了。

故事的結尾,我們把迴圈裡的查詢加以改寫,移到迴圈外,就讓客戶得到滿意的成果。

題目二:逆向工程推導資料庫綱要 (database schema)

友人入職新工作擔任資料分析師,無奈的是,新工作一上工,發現雖然有資料庫可以用,卻無法找到任何關於資料庫綱要 (database schema) 的文件。

友人與我討論之後,我建議他做兩個假設:

  1. 假設他拿到的資料庫是業務資料庫 (operational database) ,那 schema 有可能是 third normal form 。
  2. 假設他拿到的資料庫是資料倉儲 (data warehouse) ,那 schema 則有可能是 star schema 。

如果是先試假設 1 的話,就再用 grep 去搜尋看看公司的一些程式碼,是怎麼查詢資料庫的,應該可以找出資料表的名稱。有了一些資料表的名稱,再看看 primary key, foreign key 的連結關系,再搭配欄位之間的命名與資料型態,眾多資料加總起來,應該有可能推導出 database schema 。

如果假設 1 愈試卻愈奇怪的話,就再根據假設 2 ,把類似的事重做一遍。

另外,現在很多資料庫都可以與 metabase 這一類的 data visualization tool 串接,如果可以將 metabase 與資料庫串在一起,對於要逆向推導出資料庫綱要 (database schema) ,也會省事不少。

假設與架構知識

我在職場上常觀察到一種現象,『商管書籍裡談論的解題方法論,如果讓資淺的員工來使用時,常常成效也不太好。』有趣的是,失效的地方,並不是解題的方法論,而是中間有了失落的環節,缺乏的環節就前述的這些關鍵『假設』,而假設則來自於某個領域內部隱含的架構知識。

--

--

Laurence Chen

IT 顧問、講者、作家。喜歡快速迭代 (fast iteration) 與提高產出。 著作:「從錯誤到創新」 https://leanpub.com/errors_to_innovation/ 網站:https://replware.dev/