Dbdiagram.io editor is slow in nearly update

I faced into very slow when I want to delete word with about 70 tables in a diagram.
It works good in couple weeks ago. Maybe the render or validate logic changed?

Here is my DBML for your team to reproduce this situation.
You can just copy paste it and try to do some edit.

// 綠色主要為使用者和購買相關:用量高、穩定
// 藍色主要為戲劇相關:用量低、穩定
// 紅色主要為活動相關:用量通常低、依據活動情況會很極端

// 法律地區
table regions  [headercolor: #3498db] {
  id int [pk]
  name varchar
}

// 語系
table languages  [headercolor: #3498db] {
  id int [pk]
  code varchar  // 使用 ISO 命名
  name varchar
}

// 使用者
table users  [headercolor: #14C856] {
  id char(36) [pk]
  name varchar
}

// 登入方式
table oauth_gateways  [headercolor: #14C856] {
  id int [pk]
  user_id char(36) [ref: > users.id]
  oauth_gateway tinyint
  oauth_id varchar
}

// 通知方式
table notify_endpoints  [headercolor: #14C856] {
  id int [pk]
  endpoint_type tinyint // 終端種類,1: Push, 2: Email, 3. LINE OA, 4: SMS
  endpoint varchar      // 終端,Push Token | Registration ID | Phone Number | LINE OA Token | ...
  installation_id varchar
  name varchar          // 邏輯名稱
  user_id char(36) [ref: > users.id]
}

// 資源存取
table resource_statements  [headercolor: #14C856] {
  id int [pk]
  name varchar
  rule text
}

// 商品,等同現在的 Service 層級,最細的商品單元
table resource_policies  [headercolor: #14C856] {
  id int [pk]
  name varchar
}

// 商品資源
table resource_policy_statement_mappings  [headercolor: #14C856] {
  id int [pk]
  resource_policy_id int [ref: > resource_policies.id]
  resource_statement_id int [ref: > resource_statements.id]
  
  indexes {
    (resource_policy_id, resource_statement_id) [unique]
  }
}

// 付款通路,可能與展售通路直接重疊
table payment_gateways  [headercolor: #14C856] {
  id int [pk]
  name varchar
  code varchar
  
  indexes {
    (code) [unique]
  }
}

// 商品包,同目前的 category 概念,但不用另外寫程式去記背後對應的產品
// 相同 package 為可互相切換訂閱週期的群組
// TODO 上層尚未定義給 App 用的商品 API 需要的群組
table packages  [headercolor: #14C856] {
  id int [pk]
  name varchar
  square_thumb_url text   // 正方形縮圖網址
  description text
  image_url text
  link_url text
  memo_html text
  created_at bigint
  updated_at bigint
}

// 購買品項,不同通路應該要是不同品項,但內容皆為相同商品包,相同商品包即為相同性質的商品
table items  [headercolor: #14C856] {
  id int [pk]
  package_id int [ref: > packages.id]
  name varchar
  square_thumb_url text // 正方形縮圖網址
  activate_mode tinyint // 1: 立即接續啟用, 2: 手動啟用
  transfer_mode tinyint // 0: 不可轉移, 1: 啟用前可轉移 owner_id, 2: 只可轉移 holder_id
  priority int    // 優先度,預設 100,僅用來排序用,保留前面可以往前加的彈性
  status tinyint      // 0: 停用, 1: 啟用
  //started_at bigint   // 上架時間
  //expired_at bigint // 下架時間
  metadata text
  //price_label varchar // 原價文字
  //discount_price_label varchar  // 折扣價格文字
  //introductory_price_label varchar  // 入門價格文字
  //promotion_label varchar // 促銷文字
  //promotion_desc varchar  // 促銷說明
}

// 續訂用合約,讓不同時間購買的訂單可以擁有不同的價格合約
// 不可調整金額(調降或許可以?)
// 漲價等同換合約,使用者要同意。
// TODO 預設合約要如何紀錄?
table offers  [headercolor: #14C856] {
  id int [pk]
  name varchar
  square_thumb_url text   // 正方形縮圖網址
  item_id int [ref: > items.id]
  payment_gateway_id int [ref: > payment_gateways.id] // 預設付款管道
  sku varchar
  version int // 正整數: 正常合約, 負整數: 特殊合約 (限時合約,特定公司合約)
  status tinyint // 0: 停用, 1: 啟用
  visibility tinyint  // 可見等級,僅作為顯示上的過濾,部分商品可能只有特定使用者可以買 0: 全部人, 1: 會員, 2: 高級付費會員
  accessbility tinyint // 可購買等級,僅作為顯示上的過濾,部分商品可能只有特定使用者可以買 0: 全部人, 1: 會員, 2: 高級付費會員
  priority int  // 排序優先度
  started_at bigint // 啟用期間
  expired_at bigint // 結束時間
  grace_period bigint // 寬限期
  max_period int  // 合約最大週期數,-1: 無限續訂, 1: 單次購買不會續訂, 2~n: 最多續訂多少週期
  stop_renewal_at bigint // 不可再續約時間,在這時間前都還能照這合約續訂,如果是到特定時間就不能續訂而非特定週期數
  
  indexes {
    (item_id, payment_gateway_id, sku, version) [unique]
  }
}

// 使用條款(暫定)
table policies  [headercolor: #14C856] {
  id int [pk]
  platform tinyint
  scope tinyint // 0: 會員, 1: 購買類
  title varchar
  content text
  link text
  version varchar
  required tinyint
}

// 合約與所需條款對應
table offer_policy_mappings  [headercolor: #14C856] {
  id int [pk]
  policy_id int [ref: > policies.id]
  offer_id int [ref: > offers.id]
}

// 銷售管道,Web, Android, iOS, TOP, etc...
// 某些特殊合約甚至是對應上去的 item 只能在特定管道販賣
table sales_channels  [headercolor: #14C856] {
  id int [pk]
  name varchar
  region varchar
}

table offer_sales_channel_mappings  [headercolor: #14C856] {
  id int [pk]
  sales_channel_id int [ref: > sales_channels.id]
  offer_id int [ref: > offers.id]
  
  indexes {
    (sales_channel_id, offer_id) [unique]
  }
}

// 被簽署的合同,將 offer 的屬性複製一份
// 換合約用把舊的折算成 ownership 的方式
table deals  [headercolor: #14C856] {
  id int [pk]
  name varchar
  offer_id int [ref: > offers.id]
  status tinyint  // 0: 初建立尚未生效, 1: 已生效, 2: 已失效
  grace_period bigint // 寬限期
  max_period int  // 合約最大週期數,-1: 無限續訂, 1: 單次購買不會續訂, 2~n: 最多續訂多少週期
  stop_renewal_at bigint // 不可再續約時間,在這時間前都還能照這合約續訂,如果是到特定時間就不能續訂而非特定週期數
  canceled_at bigint  // 取消續訂時間
  should_renew_at bigint // 下次要檢查這份合約狀態時間
  user_cancel_reason text // 使用者自行填寫的取消理由
  capture_payment_gateway_id int [ref:> payment_gateways.id]  // 續訂付款管道
  capture_token_id int [null, ref: - line_pay_capture_tokens.id, ref: - tap_pay_capture_tokens.id]  // 續訂用的扣款 token,單次訂閱型的不會有
  terminated_reason tinyint  // 合約終止原因。 1: 使用者取消續訂終止, 2: 服務方撤銷, 3: 由金流方撤銷, 4: 合約期滿,無法續訂, 5: 與金流方持續請款失敗
  terminated_at bigint  // 合約該被終止時間,根據終止方式而定,根據 terminated_reason: 1: ownership 到期時間, 2: 若有退款則為退款完成時間, 若無則為操作當下, 3: 以金流方時間為準, 4: ownership 到期時間, 5: ownership 到期時間+寬限期 
  terminate_updated_at bigint  // 合約終止時間,被掃到的時間。
  created_at bigint
  updated_at bigint
}

// 訂單項目與合約所屬週期
// table order_item_deal_mappings  [headercolor: #14C856] {
//   id int [pk]
//   deal_id int [ref: > deals.id]
//   order_item_id int [ref: > order_deals.id]
//   period_number int
  
//   indexes {
//     (deal_id, period_number) [unique]
//   }
// }

// 合同細節,從 contrac_clauses 完整複製一份
// 方便做對特定時間點的週期做修改金額等操作,如:限時特價時要讓既有訂戶也能享有某些優惠。
table deal_clauses  [headercolor: #14C856] {
  id int [pk]
  deal_id int [ref: > deals.id]
  period_index int // 第幾個週期,0 代表預設週期,其他都是特定週期
  period bigint     // 週期長度,以毫秒為單位
  price_micro bigint  // 價格 * 1000000 避免浮點數
  description text // 描述
  
  indexes {
    (deal_id, period_index) [unique]
  }
}

// 合約中每個週期的長度與金額,才能做到不定期不定額
// 所有顯示上的價格皆與此處設定無關,不透過程式去處理
table offer_clauses  [headercolor: #14C856] {
  id int [pk]
  offer_id int [ref: > offers.id]
  period_index int // 第幾個週期,0 代表預設週期,其他都是特定週期。一次性商品的週期只會有 period_index 為 1 的。
  period bigint     // 週期長度,以毫秒為單位
  price_micro bigint  // 價格 * 1000000 避免浮點數
  description text // 描述
  
  indexes {
    (offer_id, period_index) [unique]
  }
}

// 商品包內容
table package_resource_policies  [headercolor: #14C856] {
  id int [pk]
  package_id int [ref: > packages.id]
  resource_policy_id int [ref: > resource_policies.id]
  
  indexes {
    (package_id, resource_policy_id) [unique]
  }
}

// 演藝人員,演員 or 歌手
table celebrities  [headercolor: #3498db] {
  id int [pk]
  name varchar
}

// 角色
table characters  [headercolor: #3498db] {
  id int [pk]
  name varchar
}

// 演員角色對應
table celebrity_character_mappings  [headercolor: #3498db] {
  id int [pk]
  character_id int [ref: > characters.id]
  celebrity_id int [ref: > celebrities.id]
  
  indexes {
    (character_id, celebrity_id) [unique]
  }
}

// 媒體,根據 type 區分種類
table medias  [headercolor: #3498db] {
  id int [pk]
  name varchar
  type tinyint  // 正片、預告、幕後花絮、NG 鏡頭、相關短片、二次創作
  content_id int [ref: > contents.id]
}

// 標在集數上的提示,先假設圖和文字都有可能用到,畢竟圖片比較自由
table labels  [headercolor: #3498db] {
  id int [pk]
  name varchar
  text_rgb varchar
  background_rgb varchar
  background_alpha varchar
  image_url text  // 說明頁用的大圖
  thumb_url text  // 標在集數上用的小圖
}

table media_labels  [headercolor: #3498db] {
  id int [pk]
  media_id int [ref: > medias.id]
  label_id int [ref: > labels.id]
}

table content_labels  [headercolor: #3498db] {
  id int [pk]
  content_id int [ref: > contents.id]
  label_id int [ref: > labels.id]
}

// 職位,製作人、導演...
table jobs  [headercolor: #3498db]{
  id int [pk]
  name varchar
}

// 媒體與演藝人員對應:導演、製作人、監製...
table celebrity_media_jobs  [headercolor: #3498db] {
  id int [pk]
  media_id int [ref: > medias.id]
  celebrity_id int [ref: > celebrities.id]
  job_id int [ref: > jobs.id] 
  
  indexes {
    (media_id, job_id, celebrity_id) [unique]
  }
}

// 角色對應
table media_characters  [headercolor: #3498db] {
  id int [pk]
  media_id int [ref: > medias.id]
  character_id int [ref: > characters.id]
  
  indexes {
    (media_id, character_id) [unique]
  }
}

// 字幕
table subtitles  [headercolor: #3498db] {
  id int [pk]
  timeline_id int [ref: > timelines.id]
  language_id int [ref: > languages.id]
  version int
  
  indexes {
    (timeline_id, language_id) [unique]
  }
}

// 時間軸,正常版、一刀未剪版、完整版。TODO: 動態劇情內容如何處理?
table timelines  [headercolor: #3498db] {
  id int [pk]
  name varchar
  media_id int [ref: > medias.id]
}

// 時間軸分枝,適用黑鏡這種可自由選擇劇情走向的
// 不同選項但內容相同,應該用不同的 timeline 放相同的影音 track 表示
table timeline_branches  [headercolor: #3498db] {
  id int [pk]
  name varchar
  parent_timeline_id int [ref: > timelines.id]
  child_timeline_id int [ref: > timelines.id]
  option_label varchar
  
  indexes {
    (parent_timeline_id, child_timeline_id) [unique]
  }
}

// 音軌,配音、發音
table sound_tracks  [headercolor: #3498db] {
  id int [pk]
  timeline_id int [ref: > timelines.id]
  language_id int [ref: > languages.id]
  version int
  
  indexes {
    (timeline_id, language_id) [unique]
  }
}

// 影像軌
table video_tracks  [headercolor: #3498db] {
  id int [pk]
  timeline_id int [ref: > timelines.id]
  resolution tinyint
  version int
  key varchar
}

// 觀看紀錄
table viewing_histories  [headercolor: #14C856] {
  id int [pk]
  user_id char(36) [ref: > users.id]
  timeline_id int [ref: > timelines.id]
  position bigint
  
  indexes {
    (user_id, timeline_id) [unique]
  }
}

// 集數鎖定等級時間表
// 戲劇建立時,直接選好預設的可觀看等級,新增一筆資料 timestamp 為 0~9999999999999 的資料到這
// 後續新增其他資料作為開放時間等等,查詢符合現在時間的鎖定等級資料,取最低的。就不用程式去排程更新資料,而是一開始就排定。
table region_media_accessbilities  [headercolor: #3498db] {
  id int [pk]
  region_id int [ref: > regions.id]
  media_id int [ref: > medias.id]
  accessbility tinyint  // 存取等級,0: 匿名可看, 1: 登入可看, 2: 一般付費, 3: 高階付費, 1000: Admin 可看
  started_at bigint
  end_at bigint
  
  indexes {
    (region_id, media_id, accessbility) [unique]
  }
}

// 集數顯示等級時間表
// 同等級的顯示開始時間基本上要 ≤ 鎖定開始時間。
// 切開是為了可以先顯示再解鎖,讓人有付費慾望。或是隱藏起某些特殊內容,讓特定人顯示和觀看。
table region_media_visibilities  [headercolor: #3498db] {
  id int [pk]
  region_id int [ref: > regions.id]
  media_id int [ref: > medias.id]
  visibility tinyint    // 顯示等級,0: 匿名可看, 1: 登入可看, 2: 一般付費, 3: 高階付費
  started_at bigint
  end_at bigint
  
  indexes {
    (region_id, media_id, visibility) [unique]
  }
}

// 內容,目前都是影片,之後可能會有其他的,如:音樂
table contents  [headercolor: #3498db] {
  id int [pk]
  name varchar
  
}

// 收藏
table favorites  [headercolor: #14C856] {
  id int [pk]
  user_id char(36) [ref: > users.id]
  content_id int [ref: > contents.id]
  
  indexes {
    (user_id, content_id) [unique]
  }
}

// 內容顯示時間,可區分時間讓部分人可以提早看到內容
table region_content_visibilities  [headercolor: #3498db] {
  id int [pk]
  region_id int [ref: > regions.id]
  content_id int [ref: > contents.id]
  visibility tinyint
  started_at bigint // 上架時間
  end_at bigint   // 下架時間
  
  indexes {
    (region_id, content_id, visibility) [unique]
  }
}

// 內容屬性,古裝、穿越、愛情、BL...
// TODO 多國語言
table genres  [headercolor: #3498db] {
  id int [pk]
  name varchar
  parent_genre_id int [ref: > genres.id]  // 戲劇標籤要弄成巢狀結構才符合需求
}

// 內容與屬性對應
table content_genres  [headercolor: #3498db] {
  id int [pk]
  content_id int [ref: > contents.id]
  genre_id int [ref: > genres.id]
  
  indexes {
    (content_id, genre_id) [unique]
  }
}

// 內容包,作為對商品和活動的對應用,與可看戲劇無關
table content_sets  [headercolor: #3498db] {
  id int [pk]
  name varchar
}

// 內容包與內容對應
table content_set_inclusions  [headercolor: #3498db] {
  id int [pk]
  name varchar
  content_set_id int [ref: > content_sets.id]
  content_id int [ref: > contents.id]
  
  indexes {
    (content_set_id, content_id) [unique]
  }
}

// 活動,因應未來可能會出現搶票等等類型在 campaigns 的高寫入狀況,可預先抽離。
table campaigns  [headercolor: #c0392b] {
  id int [pk]
  name varchar
}

// 活動成就
table achievements  [headercolor: #c0392b] {
  id int [pk]
  name varchar
  campaign_id int [ref: > campaigns.id]
}

// 使用者參與成就紀錄
table user_achievements  [headercolor: #c0392b] {
  id int [pk]
  user_id char(36) [ref: > users.id]
  achievement_id int [ref: > achievements.id]
  
  indexes {
    (user_id, achievement_id) [unique]
  }
}

// 使用者參與活動紀錄
table user_campaign_records  [headercolor: #c0392b] {
  id int [pk]
  user_id char(36) [ref: > users.id]
  campaign_id int [ref: > campaigns.id]
}

// 內容包與活動的對應
table content_set_campaigns  [headercolor: #c0392b] {
  id int [pk]
  content_set_id int [ref: > content_sets.id]
  campaign_id int [ref: > campaigns.id]
  
  indexes {
    (content_set_id, campaign_id) [unique]
  }
}

// 產品與活動的對應
table content_set_resource_policies  [headercolor: #14C856] {
  id int [pk]
  content_set_id int [ref: > content_sets.id]
  resource_policy_id int [ref: > resource_policies.id]
  
  indexes {
    (content_set_id, resource_policy_id) [unique]
  }
}

// 訂單
table orders  [headercolor: #14C856] {
  id int [pk]
  id_string varchar // [0-9a-zA-Z]
  init_order_id int [ref: > orders.id] // 初始訂單
  prev_order_id int [ref: - orders.id] // 訂單建立原因,續訂才有值
  payment_gateway_id int [ref:> payment_gateways.id]
  //receipt_id int [ref: - app_store_receipts.id, ref: - google_play_receipts.id, ref: - line_pay_receipts.id, ref: - so_net_receipts.id, ref: - tap_pay_receipts.id]
  creator_id char(36) [ref: > users.id] // 建立者
  payer_id char(36) [ref: > users.id]  // 付款者
  recipient_id char(36) [ref: > users.id]  // 收件人
  status tinyint  // 1: 初建立, 2: 已預約付款, 3: 預約付款失敗, 4: 已授權(OTP 通過), 5: 使用者取消(OTP 錯誤或超時), 6: 
  charged_at bigint   // 扣款成功時間
  created_at bigint   // 建立時間
  updated_at bigint   // 最新更新時間
  
  indexes {
    (id_string) [unique]
  }
}

// Apple 收據
table app_store_receipts  [headercolor: #14C856] {
  id int [pk]
  name varchar
  order_id int [ref: > orders.id]
}

// Google Play 收據
table google_play_receipts  [headercolor: #14C856] {
  id int [pk]
  name varchar
  order_id int [ref: > orders.id]
}

// LINE Pay 收據。
table line_pay_operations  [headercolor: #14C856] {
  id int [pk]
  order_id int [ref: > orders.id]
  operation_type int  // 0: Reserve, 1: Confirm, 2: Capture, 3: Preapprove 11: Void, 12: Refund(可能多次)
  // amount_micro int
  transaction_id varchar  // 不可設為 unique。試用不會有 transaction_id。授權和請款分開的其回應的 transaction_id 會一樣。
  raw_response text
  // payment_url_web varchar
  // payment_url_app varchar
  // payment_access_token  varchar
  // authorize_at bigint // 授權時間
  // authorize_expire_at bigint // 授權到期時間,此時間前必須請款
}

// Tap Pay 收據
table tap_pay_operations  [headercolor: #14C856] {
  id int [pk]
  order_id int [ref: > orders.id]
  operation_type int  // 0: Reserve, 1: Confirm, 2: Capture, 3: Preapprove 11: Void, 12: Refund(可能多次)
  rec_trade_id varchar  // 不可設為 unique。試用不會有 transaction_id。授權和請款分開的其回應的 transaction_id 會一樣。
  raw_response text
}

// So-net 收據
table so_net_receipts  [headercolor: #14C856] {
  id int [pk]
  name varchar
  order_id int [ref: > orders.id]
}

// LINE Pay 扣款用的 token 資訊,用在下次續訂
table line_pay_capture_tokens  [headercolor: #14C856] {
  id int [pk]
  name varchar
  user_id char(36) [ref: > users.id]
  reg_key varchar // 續訂才會有,單次購買不會有。訂單交易完成時,同時寫到 line_pay_capture_tokens
  status tinyint  // 1: 可用, 2: 等待註銷, 3: 已註銷
}

// LINE Pay 退款用的資訊
// table line_pay_capture_transactions  [headercolor: #14C856] {
//   id int [pk]
//   order_id int [ref: > orders.id]
//   capture_transaction_id varchar
//   status tinyint
// }

// TapPay 扣款用的 token 資訊,用在下次續訂
table tap_pay_capture_tokens  [headercolor: #14C856] {
  id int [pk]
  name varchar
  user_id char(36) [ref: > users.id]
  card_key text
  card_token text
  status tinyint  // 1: 可用, 2: 等待註銷, 3: 已註銷
}

// TapPay 退款用的 token 資訊
// table tap_pay_capture_transactions  [headercolor: #14C856] {
//   id int [pk]
//   order_id int [ref: > orders.id]
//   rec_trade_id varchar
//   status tinyint
// }

// 試用期紀錄,先假設空英這商品跨付款管道只試用一次(但 Apple 和 Google Play 的重複試用無法)
table user_package_trial  [headercolor: #14C856] {
  id int [pk]
  package_id int [ref: > packages.id]
  user_id int [ref: > users.id]
  created_at bigint
}

// 訂單內容,沒有數量,每一筆都應該會應一個 ownership
table order_deals  [headercolor: #14C856] {
  id int [pk]
  deal_id int [ref: > deals.id]
  period_index int
  order_id int [ref: > orders.id]
  status tinyint  // 商品狀態 -1: 全額退款, 0: 初建立,等待付款, 1: 已全額付款, 2: 部分退款
  user_memo text  // 使用者對商品本身的特殊需求敘述
  operator_comment text  // 服務方人為操作的備註,如只退了部分或退款原因
  revenue_amount_micro int  // 營業額,最大可退款金額
  refund_amount_micro int  // 目前退款金額
  
  indexes {
    (deal_id, period_index) [unique]
  }
}

// 序號,限兌換 1~n 次
// TODO 未設計限屬於某檔活動兌換最多幾次
table vouchers  [headercolor: #14C856] {
  id int [pk]
  code varchar
  quota bigint
  producer_id char(36) [ref: > users.id] // 來源使用者,用在使用者推薦碼類型
  
  indexes {
    code [unique]
  }
}

// 序號兌換紀錄
table voucher_redemptions  [headercolor: #14C856] {
  id int [pk]
  user_id char(36) [ref: > users.id]
  voucher_id int [ref: > vouchers.id]
}

// 客服系統
table customer_issues  [headercolor: #14C856] {
  id int [pk]
  user_id char(36) [ref: > users.id]
  title varchar
  description text
}

// 商品包擁有關係
// 考慮到家庭模式,src + src_id 不可為共同為 unique
table item_ownerships  [headercolor: #14C856] {
  id int [pk]
  item_id int [ref: > items.id]
  src tinyint
  src_id int [ref: > order_deals.id, ref: > voucher_redemptions.id, ref: > customer_issues.id, ref: > user_achievements.id]
  owner_id char(36) [ref: > users.id]
  holder_id char(36) [ref: > users.id]
  activate_at bigint
  expired_at bigint
}
1 Like

Hi @Cateyes_Lin
Sorry for the inconvenience, please provide us with more information about your browser (with version) and OS so that we can support you better with this issue.

OSX 10.13 High Sierra with Chrome 80.0.3987.132

Having the same problem. I’m at 117 tables or so (with a lot more coming) and finding it incredibly slow to the point of freezing on me for a second or two at a time.

MacOS Catalina 10.15.3
Chrome version: 80.0.3987.132

Once again, sorry for the inconvenience, we are having a performance issue with Chrome on large number of tables, however other browsers such as Firefox work just fine.

We suggest using Firefox for now if you are working on a big diagram (more than 50 tables) while we are investigating the issue on Google Chrome.

We’ll keep you informed when any progress has been made.

1 Like