Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ndb
Search
spicyj
May 28, 2014
Technology
0
130
ndb
spicyj
May 28, 2014
Tweet
Share
More Decks by spicyj
See All by spicyj
React: What Lies Ahead
spicyj
6
370
Creating interactive learning interfaces at Khan Academy
spicyj
0
110
Understanding state in React
spicyj
1
110
css
spicyj
2
860
Other Decks in Technology
See All in Technology
All About Sansan – for New Global Engineers
sansan33
PRO
1
1.3k
AI駆動開発を実現するためのアーキテクチャと取り組み
baseballyama
17
15k
一億総業務改善を支える社内AIエージェント基盤の要諦
yukukotani
4
1.9k
GitHub を組織的に使いこなすために ソニーが実践した全社展開のプラクティス
sony
14
8.5k
Codeer.LowCode.Blazor 紹介と成長録
wadawada
0
110
AI エージェントを評価するための温故知新と Spec Driven Evaluation
icoxfog417
PRO
2
960
Contract One Engineering Unit 紹介資料
sansan33
PRO
0
9.7k
Excelデータ分析で学ぶディメンショナルモデリング ~アジャイルデータモデリングへ向けて~ by @Kazaneya_PR / 20251126
kazaneya
PRO
3
660
20251127 BigQueryリモート関数で作る、お手軽AIバッチ実行環境
daimatz
0
320
Digital omtanke på Internetdagarna 2025
axbom
PRO
0
140
履歴テーブル、今回はこう作りました 〜 Delegated Types編 〜 / How We Built Our History Table This Time — With Delegated Types
moznion
8
5.9k
『星の世界の地図の話: Google Sky MapをAI Agentでよみがえらせる』 - Google Developers DevFest Tokyo 2025
taniiicom
0
430
Featured
See All Featured
Build your cross-platform service in a week with App Engine
jlugia
234
18k
Context Engineering - Making Every Token Count
addyosmani
9
440
The Cult of Friendly URLs
andyhume
79
6.7k
Docker and Python
trallard
46
3.7k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
34
2.3k
Site-Speed That Sticks
csswizardry
13
970
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.2k
Done Done
chrislema
186
16k
How to Think Like a Performance Engineer
csswizardry
28
2.3k
Transcript
ndb “NDB is a better datastore API for the Google
App Engine Python runtime.”
Part 1 of 2
Why ndb? 1. Less stupid by default 2. More flexible
queries 3. Tasklets with autobatching
Less stupid by default With db: class UserVideo(db.Model): user_id =
db.StringProperty() video = db.ReferenceProperty(Video) user_video = UserVideo.get_for_video_and_user_data( video, user_data) return jsonify(user_video) # slow
Less stupid by default With ndb: class UserVideo(ndb.Model): user_id =
ndb.StringProperty() video = ndb.KeyProperty(kind=Video) user_video = UserVideo.get_for_video_and_user_data( video, user_data) return jsonify(user_video) # not slow!
More flexible queries ndb lets you build filters using ndb.AND
and ndb.OR: questions = Feedback.query() .filter(Feedback.type == 'question') .filter(Feedback.target == video_key) .filter(ndb.OR( Feedback.is_visible_to_public == True, Feedback.author_user_id == current_id)) .fetch(1000) Magic happens.
Performance The datastore is slow. How can we speed things
up? 4 Batch operations together 4 Do things in parallel 4 Avoid the datastore
Tasklets and autobatching def get_user_exercise_cache(user_data): uec = UEC.get_for_user_data(user_data) if not
uec: user_exercises = UE.get_all(user_data) uec = UEC.build(user_exercises) return uec def get_all_uecs(user_datas): return map(get_user_exercise_cache, user_datas)
Tasklets and autobatching @ndb.tasklet def get_user_exercise_cache_async(user_data): uec = yield UEC.get_for_user_data_async(user_data)
if not uec: user_exercises = yield UE.get_all(user_data) uec = UEC.build(user_exercises) raise ndb.Return(uec) @ndb.synctasklet def get_all_uecs(user_datas): uecs = yield map(get_user_exercise_cache_async, user_datas) raise ndb.Return(uecs)
Moral ndb is awesome. Use it.
Part 2 of 2
The sad truth ndb isn't perfect.
Mysterious errors You heard from Marcia about this gem back
in March: TypeError: '_BaseValue' object is not subscriptable
Q: What's worse than code that doesn't work at all?
A: Code that mostly works but breaks in subtle ways.
Secret slowness #1 Multi-queries, with IN and OR: answers =
Feedback.query() .filter(Feedback.type == 'answer') .filter(Feedback.in_reply_to.IN(question_keys)) .fetch(1000) Doesn't run in parallel!
Secret slowness #1 A not-horribly-slow multi-query: answers = Feedback.query() .filter(Feedback.type
== 'answer') .filter(Feedback.in_reply_to.IN(question_keys)) .order(Feedback.__key__) .fetch(1000)
Secret slowness #2 Query iterators: query = Feedback.query().filter( Feedback.topic_ids ==
'algebra') questions = [] for q in query.iter(batch_size=20): if q.is_visible_to(user_data): questions.append(q) if len(questions) >= 10: break
Secret slowness #2 Solution? Sometimes you have to do it
by hand.
Moral ndb isn't perfect. Pay attention. Profile your code.
The End