iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 20
0
Mobile Development

老姐好像要用 Kotlin 寫專案,能撐30天嗎?系列 第 20

節省開支的第二十天:Eager loading 原理——快取和 IN 運算子

老姐經過我身邊的時候看了一下我的螢幕,好奇的問:「下方這些 log 像是 SQL 指令?」

https://ithelp.ithome.com.tw/upload/images/20200929/20129197IBm9r3OMUz.png

「對呀, Exposed 會把 DAO 用的 SQL 指令印出來,方便我校對邏輯或是改善查詢方式。像是妳剛剛看到的那幾行邏輯沒錯,但是查詢次數太多了,考慮到雲端服務會用資料庫查詢次數計價,最好使用 Eager loading 。」

「那是什麼?」老姐表示這個專有名詞她沒印象。

直接解釋有點抽象,所以我打開資料庫相關程式碼檔案秀給她看。「我的題目 table 有參考到其他 table ,比如作者是使用者 table,標籤也有標籤 table。」

object Topics : UUIDTable() {
    val tags = reference("tags", TopicTags)
    val author =  reference("author", Users)
    ...
}
class Topic(id: EntityID<UUID>) : UUIDEntity(id) {
    companion object : UUIDEntityClass<Topic>(Topics)
    
    ...
    var author by User referencedOn Topics.author
    var tags by TopicTag referencedOn Topics.tags
    val chats by Chat.referrersOn(Chats.topic,true)
}

「題目列表直接拿的話,裡面每讀一個題目都要查詢一次作者和標籤。總題數如果是 N ,查詢量就是 1 + 2 * N。」

020-09-29 20:46:49.344 [nioEventLoopGroup-4-1] DEBUG Exposed - SELECT TOPICS.ID, TOPICS.TITLE, TOPICS.DESCRIPTION, TOPICS.TAGS, TOPICS.AUTHOR, TOPICS.COMPLETED, TOPICS.CREATED_AT, TOPICS.UPDATED_AT FROM TOPICS
2020-09-29 20:46:49.353 [nioEventLoopGroup-4-1] DEBUG Exposed - SELECT USERS.ID, USERS.AVATAR, USERS."NAME" FROM USERS WHERE USERS.ID = '64f5c7f3-9c4e-4397-8e0e-5113be4186e0'
2020-09-29 20:46:49.354 [nioEventLoopGroup-4-1] DEBUG Exposed - SELECT TOPICTAGS.ID, TOPICTAGS.TAGS, TOPICTAGS.CREATED_AT FROM TOPICTAGS WHERE TOPICTAGS.ID = '2f80dccb-2a38-4f32-b2df-0aa91b636101'
...

「如果利用快取,查詢量就會是 1+1+1 次,第一次拿題目串,第二次拿這些題目作者,第三次拿這些題目標籤。然後利用程式配對組合。利用 IN 運算子 達成範圍查詢。 」

2020-09-29 20:46:49.365 [nioEventLoopGroup-4-1] DEBUG Exposed - SELECT TOPICS.ID, TOPICS.TITLE, TOPICS.DESCRIPTION, TOPICS.TAGS, TOPICS.AUTHOR, TOPICS.COMPLETED, TOPICS.CREATED_AT, TOPICS.UPDATED_AT FROM TOPICS
2020-09-29 20:46:49.451 [nioEventLoopGroup-4-1] DEBUG Exposed - SELECT USERS.ID, USERS.AVATAR, USERS."NAME" FROM USERS WHERE USERS.ID IN ('1892daf3-a10d-45be-bf01-857723f48f84', '64f5c7f3-9c4e-4397-8e0e-5113be4186e0', '97ce0cf7-8765-4d3b-bccf-7c6d80e84218', 'a5908650-a919-4a2e-9f14-6a990d658814', 'c6bcd1ff-8d50-4637-ad54-42f58cb48026', 'd3f85e90-debe-44be-830f-9fbb7715dc45', 'ea638493-8d52-4732-a843-41df01b0281f')
2020-09-29 20:46:49.452 [nioEventLoopGroup-4-1] DEBUG Exposed - SELECT TOPICTAGS.ID, TOPICTAGS.TAGS, TOPICTAGS.CREATED_AT FROM TOPICTAGS WHERE TOPICTAGS.ID IN ('2f80dccb-2a38-4f32-b2df-0aa91b636101', '46d94d7f-e856-401a-8203-e786650f2904', '7ac74d60-45f4-4848-a884-895caced9c06', '9a3350cb-dfaa-4180-a66f-768da3eb8ce0')

「原來如此,那 DAO 程式碼寫法差別在哪?」老姐看懂了。

「只要在 with 括號裡面註明要一筆拿的參考欄位就可以。」

                    //Topic.all().map {//直接拿
                    Topic.all().with(Topic::author, Topic::tags).map {//Eager loading
                       TopicResponse(
                           id = it.id.value,
                           name = it.title,
                           avatar = it.author.avatar,
                           attendance = (0..10).random().toString() + "人",
                           tags = it.tags.title
                       )
                   }
    //val chats by Chat referrersOn Chats.topic//新版本才支援預設快取
    val chats by Chat.referrersOn(Chats.topic,true)

我突然想起來很重要的一件事,「對了,如果欄位用的是 referrersOn 要注意,目前最新的版本 0.27.1 還沒預設快取,要另外設定。官網的 issue 有說未來會改。」

https://github.com/JetBrains/Exposed/issues/1046
https://ithelp.ithome.com.tw/upload/images/20200929/20129197acyqhBgARr.png

老姐滿臉困惑的說:「我剛剛就想問 referrersOnreferencedOn 的意思了。」

「兩者是鏡射關係,A referencedOn B 就會造成 B referrersOn A。以我們題目和作者的關係來說,題目建立會記錄作者是誰,因此可以反過來查該作者有建立多少題目。」

class User(id: EntityID<UUID>) : UUIDEntity(id) {
    companion object : UUIDEntityClass<User>(Users)

    ...
    val topics by Topic.referrersOn(Topics.author, true)
}

我說著乾脆連 DAO Wiki 網頁都拿出來:「想知道更多 DAO 可以看這邊介紹 https://github.com/JetBrains/Exposed/wiki/DAO ,我也是聽人說 Eager loading 後到這邊研究的。」

https://ithelp.ithome.com.tw/upload/images/20200929/20129197Qjk6QLRlzi.png

本次鐵人賽的作品在放進更多內容後已經成書,書名是《老姐要用Kotlin寫專案:從 Server 到 Android APP 的開發生存日記》,歡迎購買唷。https://www.tenlong.com.tw/products/9789864348978


上一篇
模型設計的第十九天:問答聊天室結構
下一篇
家家烤肉的第二十一天:攔截 Route 製作專屬處理
系列文
老姐好像要用 Kotlin 寫專案,能撐30天嗎?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言