YouTube2Text

Design Good Schemas - Get a Better Database - Nuri Halperin - NDC Oslo 2023 — Transcript

by NDC Conferences · 9,083 words · 1,393 segments · language en · Watch on YouTube

Full transcript

  1. 0:02uh my name is Nuri I'm going to be
  2. 0:04talking about designing a good schema uh
  3. 0:08to get better results
  4. 0:11um I've been a developer to start with
  5. 0:14Delta lot with back end our database or
  6. 0:18data structures been doing a lot of data
  7. 0:20migrations lately been doing a lot of
  8. 0:22c-sharp in my career
  9. 0:24also other programming languages python
  10. 0:27JavaScript stuff like that
  11. 0:30and since I've been around I figured I
  12. 0:32put the stock together just to kind of
  13. 0:34share my experience about what worked
  14. 0:37short term what worked longer term and
  15. 0:40this is really about trying to optimize
  16. 0:43for longer term so if I break down the
  17. 0:46slide into what I'm really looking at
  18. 0:50the use case scenario I'm kind of
  19. 0:51envisioning here is that as a developer
  20. 0:55I want a good schema that I won't regret
  21. 0:58later
  22. 0:59and we've all been there or maybe
  23. 1:01haven't
  24. 1:03um that we designed something we thought
  25. 1:06it's great we thought it's quick we
  26. 1:08thought we fulfilled everything just to
  27. 1:10find out that after delivering the first
  28. 1:13iteration or the first iteration into
  29. 1:15test or living with it for a year or
  30. 1:18five uh you discover all of these things
  31. 1:21that all of these decisions that seemed
  32. 1:23right at the time and turned out not to
  33. 1:25be optimal
  34. 1:27so breaking it down a little more we
  35. 1:30have to ask ourselves well good scheme
  36. 1:32assam's color qualifying what is the
  37. 1:34word good like what do I mean by that
  38. 1:36okay that's a fair question so
  39. 1:40the fitness criteria I'm looking for I
  40. 1:43need to stay in this song because
  41. 1:44otherwise I'm walking off camera okay
  42. 1:46it's here so the fitness criteria I'm
  43. 1:49looking for are roughly that the schema
  44. 1:53really wants to solve a business problem
  45. 1:58um
  46. 2:00so what would be not a business problem
  47. 2:03like making my boss happy would not be a
  48. 2:05business problem if it serves a customer
  49. 2:07yes it's a big it's a business problem
  50. 2:10but if it doesn't it really doesn't
  51. 2:11belong in the things I need to solve
  52. 2:14so you gotta watch out for requirement
  53. 2:16creeps that tell you how to do things
  54. 2:18that has nothing to do with the real
  55. 2:20business problem you're solving and
  56. 2:23within what you're solving for the real
  57. 2:25business you want to make sure that it
  58. 2:29doesn't uh scope creep into things that
  59. 2:33are not in the real world that are
  60. 2:35internal technical things that can creep
  61. 2:39in and pressure you to make schema
  62. 2:41decisions based on that that don't
  63. 2:43belong to solving so it's the size of
  64. 2:46the actual word that I care about and
  65. 2:48the things that serve that fit in the
  66. 2:51things that don't maybe a little less so
  67. 2:53and the schema should be easy to reason
  68. 2:55with right note the future self I need
  69. 2:58to read this later I need to communicate
  70. 3:01this with a team I need everybody to be
  71. 3:03on the same page and understand it I
  72. 3:05don't want something so convoluted that
  73. 3:08is so difficult to use
  74. 3:10one example of that has anybody heard of
  75. 3:13eav entity attribute value
  76. 3:17type schemas one over there
  77. 3:21um
  78. 3:21if we have time I can go into this big
  79. 3:25anti-pattern for for any kind of medium
  80. 3:29to large scale it's a way to represent
  81. 3:31things in a very flexible way in
  82. 3:33databases schemas that were designed to
  83. 3:36be rigid and well defined
  84. 3:40the disaster with that is that querying
  85. 3:42this thing in any kind of way is is just
  86. 3:46kind of horrific and convoluted and very
  87. 3:48difficult to reason with
  88. 3:51and finally I wanted to be change
  89. 3:52tolerant so in the interest of future
  90. 3:57self I want to be able to evolve this as
  91. 4:01my product evolves as our business case
  92. 4:03evolves with a minimal set of impact
  93. 4:10and I'm saying model
  94. 4:11but we got to talk about this for a
  95. 4:13second because that's a design thing
  96. 4:16model versus schema so in the title I
  97. 4:20put schema and schema is very specific
  98. 4:21model the real world is out there it's
  99. 4:24well we're in it right we're right here
  100. 4:27and this is the domain this is the area
  101. 4:30in which we talk about models
  102. 4:33so I can model a person I can look at
  103. 4:37real world things about a person their
  104. 4:40height uh how they're dressed uh their
  105. 4:43hair color if they have any uh things
  106. 4:46like that
  107. 4:47that was a joke sorry okay
  108. 4:49thank you
  109. 4:51and then in the database world when
  110. 4:54we're talking about stuff we're talking
  111. 4:55about schema we're talking really about
  112. 4:57the structures of how the data is
  113. 5:00actually stored and that dictates how it
  114. 5:03would be processed and the most
  115. 5:06important thing is the design so the
  116. 5:09design is moving from the world the real
  117. 5:13world the model into the schema
  118. 5:18a model represents the
  119. 5:21uh real world
  120. 5:25did you notice it looks like a smiley I
  121. 5:27don't know I kind of liked it uh a model
  122. 5:29represents the real world uh so the
  123. 5:32model is looking at a person looking at
  124. 5:35properties that I can see looking at a I
  125. 5:39don't know an oil rig a pipe a whatever
  126. 5:43it is we represent a catalog item is a
  127. 5:46product right so catalog item belongs
  128. 5:49into this idea that we have some kind of
  129. 5:52catalog maybe it's a real printable
  130. 5:54catalog and there's items that I show in
  131. 5:56the brochure and now I show it in the
  132. 5:58web but that's representative of the
  133. 6:02real world I pick out things that are
  134. 6:05observable about the thing I'm trying to
  135. 6:08represent so a catalog item has a name
  136. 6:13and I give it a name it has some
  137. 6:16measurements things like that and it's
  138. 6:19the stuff I care about for business
  139. 6:21so if I care about its weight then it's
  140. 6:25in my model and if I don't care about
  141. 6:27its weight it's not in my model as
  142. 6:29simple as that
  143. 6:31schema on their other hand schema
  144. 6:33implements the model so once we came up
  145. 6:37with what we care about from the
  146. 6:40business perspective from The Real World
  147. 6:43then we design we can move into schema
  148. 6:46land and schema land is where we get to
  149. 6:49speak a different language
  150. 6:53because when I say an item has a weight
  151. 6:57there is no weight inside computer
  152. 7:00language
  153. 7:02there's numbers I can pick the right
  154. 7:05number for it or the right
  155. 7:07representation for whatever I'm trying
  156. 7:08to do so I can say oh a weight is just a
  157. 7:12decimal representation of the weight in
  158. 7:14kilograms or in grams or in pounds or
  159. 7:17stone or whatever I want
  160. 7:19but there is no weight inside SQL SQL is
  161. 7:23its own language
  162. 7:24so really we're going to start
  163. 7:26translating things that in the real
  164. 7:28world were expressed in all of the terms
  165. 7:30we know in our own language of what we
  166. 7:33speak speaking language and translating
  167. 7:36it into schema in some way
  168. 7:39and it describes an entity graph
  169. 7:42in that when we have things and I have
  170. 7:46an item and I have a catalog that's a
  171. 7:48graph that's a representation of
  172. 7:50relationships between different things a
  173. 7:53catalog item to a catalog in invoice of
  174. 7:57you know a piece of paper that details
  175. 7:59you know the customer and the items they
  176. 8:02have in their shopping cart or stuff
  177. 8:04like that their prices the totals all of
  178. 8:07these kind of things so all of these
  179. 8:09things are relationships between things
  180. 8:10and
  181. 8:12um I just say this is a graph this is a
  182. 8:15a representation of nodes with
  183. 8:18connections between them
  184. 8:21it can describe
  185. 8:24constraints on values so that's a domain
  186. 8:28of schema so when I say hey I have
  187. 8:31countries in the real world that's in my
  188. 8:33model
  189. 8:34in SQL there is no country's data type
  190. 8:38right there's a stringy data type
  191. 8:40there's a numeric data type there's all
  192. 8:43kinds of things I can say okay well you
  193. 8:46know I'll store it in a chart too
  194. 8:48because I have ISO two letter codes for
  195. 8:51all countries that would be called a
  196. 8:53domain so it's a type meaning car Char
  197. 8:57whatever you want and it has
  198. 9:00restrictions on what values it has it
  199. 9:03doesn't have to be restriction it could
  200. 9:04be looked as allow us but in any case
  201. 9:07I'm describing that when I store this
  202. 9:09stuff it better be in that domain
  203. 9:12and some databases actually support this
  204. 9:16notion and allow you to declare a domain
  205. 9:18it's it's a it's a pretty pretty rare to
  206. 9:22see that people really use domain more
  207. 9:24likely they're using what's called
  208. 9:25domain tables which is just creating a
  209. 9:28table and saying ah this table is the
  210. 9:31universe of all values that could be
  211. 9:32ever used for a country
  212. 9:35and
  213. 9:36your mileage may vary I'm not talking
  214. 9:38about specific database implementation
  215. 9:41here so
  216. 9:43um you know you may find that you want
  217. 9:44to use domains you may find that you
  218. 9:46want to use the more generic
  219. 9:48implementation of domain tables to
  220. 9:51restrict which values can go in
  221. 9:55and finally the schema layout will
  222. 9:59actually impact your performance and
  223. 10:01this is where I recommend to not come to
  224. 10:03my talk but go and hit the books talk to
  225. 10:06your dbas uh go to courses study on your
  226. 10:09own read the manual however you find a
  227. 10:13way to learn more about the
  228. 10:14implementation the engine itself how it
  229. 10:17works the better your performance will
  230. 10:20be because as it turns out your schema
  231. 10:23could be
  232. 10:24implemented you can Define tables with
  233. 10:28partitions you can define various
  234. 10:30indexing strategies clustered indexes
  235. 10:33all kinds of things that will
  236. 10:35vastly improve your performance or
  237. 10:38totally kill it depending on what
  238. 10:41choices you make so this is where beyond
  239. 10:43the concept of schema and just saying
  240. 10:45using generic ddl data definition
  241. 10:48language to describe my tables and my
  242. 10:52stuff you can go in and use the
  243. 10:54optimization that each engine provides
  244. 10:57for you in order to create say a
  245. 10:59partition table in order to map
  246. 11:00partitions to files files groups things
  247. 11:03like that those kind of things if you
  248. 11:06get deep into it can help you a lot
  249. 11:10and those tend to fold in a lot more
  250. 11:13knowledge of not just the model but how
  251. 11:16your use case is going to lay out on
  252. 11:18that meaning how often are you going to
  253. 11:20access things at what rate how much data
  254. 11:24you expect things like that
  255. 11:29and the main thing is I don't want to
  256. 11:31regret it right I don't want to make
  257. 11:32things that decisions today that I will
  258. 11:36regret tomorrow so the question is what
  259. 11:38will I regret tomorrow I can tell you a
  260. 11:41few things I regretted one is things
  261. 11:44were way too complicated too complicated
  262. 11:47I I did the eav model once regretted it
  263. 11:50wholeheartedly it's a complex way to
  264. 11:53represent flexible objects and
  265. 11:55relational databases are just not built
  266. 11:58for that so every query and everything
  267. 12:00we wanted to do it was an uphill battle
  268. 12:04downtime when changes were too vast when
  269. 12:07I needed to make a change and it
  270. 12:10required me to take the database offline
  271. 12:12and therefore the applications I talk to
  272. 12:13it offline that's very painful
  273. 12:16and just lots of work if the changes are
  274. 12:20possible but just require a ton of work
  275. 12:22that's big investment that's more
  276. 12:24planning that's more involvement of more
  277. 12:26people that's harder to roll into
  278. 12:28production so those are all regrettable
  279. 12:31decisions
  280. 12:35so in terms of work
  281. 12:39I kind of put together this thing and um
  282. 12:42it it it's DB engine specific
  283. 12:46but I think it's worth staring at for a
  284. 12:48little bit
  285. 12:50um I tried to say well
  286. 12:52how do we break down what is the impact
  287. 12:56of change if I want to change something
  288. 12:59what does it involve
  289. 13:01so in terms of ddl and we're talking
  290. 13:04about the data definition language how
  291. 13:06my tables are declared what do I declare
  292. 13:09I declare that there is a table or there
  293. 13:11isn't
  294. 13:12right create a table okay that's cheap
  295. 13:15just create a new table nobody used it
  296. 13:18before what's my dependencies another
  297. 13:20just about zero right I can do that all
  298. 13:22day
  299. 13:24but if I drop a table I gotta ask myself
  300. 13:27hey was the stable involved with anybody
  301. 13:30else was it part of a graph with other
  302. 13:32things in which case you know there may
  303. 13:35be a little more impact or high impact
  304. 13:37depending on how uh how interconnected
  305. 13:40how many foreign Keys it has to other
  306. 13:42things
  307. 13:44so dropping a table and creating a table
  308. 13:47not the same and dropping a table that
  309. 13:50has strings and tentacles to other stuff
  310. 13:52more expensive
  311. 13:54adding a column with a null value
  312. 13:57generally considered a zero cost
  313. 14:00operation populating it with values can
  314. 14:03take a little more
  315. 14:05huge huge tables even more but still
  316. 14:08it's within the realm of kinda easy
  317. 14:09right
  318. 14:11but if this was involved with other key
  319. 14:16constraints if the column was involved
  320. 14:20in some constraints then we have to take
  321. 14:23more care it's not a zero time operation
  322. 14:27on large tables when you manipulate
  323. 14:30columns that participate in foreign key
  324. 14:32that's where your complexity suddenly
  325. 14:35starts that's where interconnectivity
  326. 14:38shows up and then you may have cascading
  327. 14:41updates in other places so that costs
  328. 14:43more
  329. 14:46um talking about dropping column kind of
  330. 14:49similar to dropping a table that has
  331. 14:51that column because it all has to do
  332. 14:53with these interconnected with this
  333. 14:55graph of objects that interact with each
  334. 14:58other
  335. 15:00and finally changing a column type
  336. 15:05it kind of depends if your column types
  337. 15:08become
  338. 15:10um
  339. 15:11if if you had a numeric that was too
  340. 15:15narrow and you widened it you're really
  341. 15:17more accommodating if you're taking a
  342. 15:20type and changing it completely it was
  343. 15:22string and now it's an INT anybody that
  344. 15:24treated it before a string and wanted to
  345. 15:26parse it now has to worry about it so
  346. 15:30that's a more sweeping change
  347. 15:33um and then if you're narrowing
  348. 15:35something if you're taking something
  349. 15:36that was open and making it more
  350. 15:38restrictive
  351. 15:39then again you have to worry about
  352. 15:42everybody that was using it making sure
  353. 15:44their math isn't harmed making sure your
  354. 15:47data didn't lose Precision without you
  355. 15:50knowing and intending to do that
  356. 15:53so it's kind of good I think to map
  357. 15:56the impact of the changes I anticipate
  358. 15:59or the changes I might experience as a
  359. 16:03result of changing constraints to map it
  360. 16:06mentally to like what's the cost of this
  361. 16:08change
  362. 16:09and if you start with that then when
  363. 16:12you're designing you say okay I'm doing
  364. 16:14this decision
  365. 16:15now what if I had to change it what
  366. 16:17changes can happen to it and based on
  367. 16:20that I can try to project well is it
  368. 16:23advisable to do today
  369. 16:27So based on what I just said I would
  370. 16:29start with
  371. 16:30seven ish kind of areas that I marked as
  372. 16:35uh errors or things to know or things to
  373. 16:38do that might make your life better or
  374. 16:40pick data types
  375. 16:41opaque data types are data types that
  376. 16:44don't represent a single thing or don't
  377. 16:48represent anything for the database
  378. 16:49itself
  379. 16:50a composed string
  380. 16:52can be an opaque data type
  381. 16:55if I have
  382. 16:57full name as a field in my database
  383. 17:01or a column in my database I should say
  384. 17:03and I always treat it as just full name
  385. 17:07my database is just for label printing I
  386. 17:10put in the name it's part of the address
  387. 17:12is full name it's just a thing that
  388. 17:15appears on the line I never care if it's
  389. 17:18Nuri Halperin or Bob Smith or Jane J
  390. 17:23Smith or whatever it is doesn't matter
  391. 17:27but it becomes an opaque data type if in
  392. 17:30my business requirements I need to then
  393. 17:33go and sort it by last name
  394. 17:36because the database has no idea that
  395. 17:39within this string
  396. 17:40there's some spaces and they mean
  397. 17:42something and then that the last part of
  398. 17:46it is actually the last name
  399. 17:48and sometimes last names are multi-word
  400. 17:52last names so actually counting and
  401. 17:55going to the last is not going to work
  402. 17:56and the database has no idea about it
  403. 17:59right the database is just varchar and
  404. 18:02varchar right as programmers we think
  405. 18:04string but same thing the database even
  406. 18:07in string it's opaque because it has
  407. 18:09multiple parts
  408. 18:11so doing that
  409. 18:13messes you up later it's better if you
  410. 18:16know that there are constituents to a
  411. 18:18thing to break it apart into its
  412. 18:21constituents
  413. 18:22blob for the same reason a blob is
  414. 18:25something that maybe doesn't have
  415. 18:27delimiters naturally in it or that they
  416. 18:30are not even attainable within the SQL
  417. 18:33language a byte string would be
  418. 18:38a good example for that where
  419. 18:42um you know it's just a sequence of
  420. 18:44bytes and sure in programming I know how
  421. 18:47to scroll in and use protobufs and hop
  422. 18:50into the right byte to extract the field
  423. 18:52from it but as far as the database is
  424. 18:54concerned it's a blob
  425. 18:56image data jpegs inside the database
  426. 19:01I I never not regretted putting binary
  427. 19:05data in the database like there's an app
  428. 19:07for that it's called the file system
  429. 19:09it's called buckets
  430. 19:12store the pointer
  431. 19:13those are things for those are
  432. 19:17infrastructure for these things in the
  433. 19:19database keep things that are relational
  434. 19:21that are property that are processable
  435. 19:23processible with logical operators
  436. 19:27I can't say image one greater than image
  437. 19:30image two makes no sense I can't scroll
  438. 19:34in there and even tell you if it's an
  439. 19:36exif A J fifth or a gif or a gif can't
  440. 19:40say any of that just don't know
  441. 19:43and Json and XML suffer some from some
  442. 19:46stuff that is very similar except as
  443. 19:49humans we can say oh what do you mean I
  444. 19:52understand these delimiters
  445. 19:54but the database doesn't so don't do
  446. 19:57that
  447. 19:59incorrect data types you know dates as
  448. 20:02strings is the most often seen one in my
  449. 20:05experience it's just using the database
  450. 20:09uh to store seemingly flexible data type
  451. 20:13or just shuttling it from the front end
  452. 20:16and having no marshalling so I can show
  453. 20:18it as a string again the database
  454. 20:21doesn't know how to compare it correctly
  455. 20:23at best you will do an ISO
  456. 20:26representation that is canonical and you
  457. 20:28can do comparisons of greater less than
  458. 20:31but then you'll have to break it apart
  459. 20:33look at constituent of the time time
  460. 20:36zone offset things like that
  461. 20:38ugly stuff there is a database data type
  462. 20:41for that in the database knows how to do
  463. 20:44things like extract the time zone the
  464. 20:46minute the second the whatever from
  465. 20:48proper date types so use the proper date
  466. 20:52time
  467. 20:53and finally non-domain values it's not
  468. 20:57something you do in your ddl so much but
  469. 21:01if in your column you're going to shove
  470. 21:03some random value that is not from your
  471. 21:05domain
  472. 21:06like you have all country codes and then
  473. 21:09you represent Country Code Zero for all
  474. 21:11of those that you don't know the country
  475. 21:13code
  476. 21:14that's wrong and putting null is also
  477. 21:17not something from the domain
  478. 21:19null
  479. 21:20is it a type is it a value it's not a
  480. 21:23value it's a type right and it doesn't
  481. 21:25belong to the country codes there is no
  482. 21:27country in the world that is null
  483. 21:30right so it's a non-domain value and
  484. 21:33non-domain values mean that the database
  485. 21:36doesn't know that it doesn't belong
  486. 21:38there so all comparisons are going to
  487. 21:40run against it as if it's just part of
  488. 21:43the domain but in fact it isn't and you
  489. 21:46will have to write extra logic to handle
  490. 21:48it everywhere
  491. 21:49so don't store values that don't belong
  492. 21:52to the domain that you intended
  493. 21:58how do we fix OPEC data types I created
  494. 22:02a I think I talked about
  495. 22:05the OPEC data type issues
  496. 22:09um
  497. 22:12that SQL language is not made to do it
  498. 22:14there's limited support and opaque data
  499. 22:18types and non-domain values are are hard
  500. 22:22to deal with and just inject a lot of
  501. 22:25logic and later on you'll have to undo
  502. 22:27that or change it or handle it
  503. 22:29everywhere it just kind of spiders
  504. 22:31throughout your organization so how to
  505. 22:33fix it
  506. 22:35it's pretty simple it looks cunningly
  507. 22:37like
  508. 22:38denormalization templates uh except I
  509. 22:43don't love the word denormalization
  510. 22:46um
  511. 22:47you start with a value
  512. 22:49you have in your domain something you
  513. 22:51need to represent it you stare at it and
  514. 22:54you ask yourself is it atomic is it
  515. 22:57Atomic yes I can map it directly to a
  516. 23:00SQL data type
  517. 23:02if it's so that's the top branch on the
  518. 23:06train then I've won let's see if pointer
  519. 23:09technology works here
  520. 23:11so you go in here is it Atomic yes great
  521. 23:15good you just encode it as a SQL native
  522. 23:19type and you've won you come in and it's
  523. 23:22not atomic
  524. 23:23and now the question is what's it what
  525. 23:26is its non-atomicity
  526. 23:28is it because it's actually a set of
  527. 23:31properties like you took a dictionary
  528. 23:33and tried to shove it into Json
  529. 23:37if you did that then this is a key value
  530. 23:40really it's this Branch right here
  531. 23:44and each key really wants to be a column
  532. 23:47the way to represent things in a SQL
  533. 23:51database is assigning a column with a
  534. 23:53proper data type nanopic
  535. 23:56so you take each one of the keys you
  536. 23:59turn it into a column name and you stare
  537. 24:01at the value
  538. 24:02but you're not done because that value
  539. 24:05in itself
  540. 24:07you have to look at it and ask yourself
  541. 24:08again is it Atomic yes okay I've won I'm
  542. 24:12done with my column no it's not okay
  543. 24:15well ask yourself again is it a
  544. 24:18dictionary with keys and values in which
  545. 24:20case you want to break it or is it a
  546. 24:23sequence of items
  547. 24:24maybe you have an array masquerading as
  548. 24:27XML or something like that
  549. 24:29or maybe you have a train of values
  550. 24:32represented by some buffer or something
  551. 24:35like that and they are actually an array
  552. 24:37or a set of things
  553. 24:40so then the answer there is well if it's
  554. 24:43a set of things since columns in SQL
  555. 24:46better be Atomic that means I need a
  556. 24:49different table
  557. 24:51so it's going to become a column in
  558. 24:54another table with a reference back to
  559. 24:57the parent table
  560. 25:00so that's my algorithm there
  561. 25:07make sense
  562. 25:08any questions on that
  563. 25:11okay
  564. 25:16which brings us to
  565. 25:18air 2. I see a lot
  566. 25:21multi-entity table
  567. 25:22multi-entity table is a generalized
  568. 25:25table
  569. 25:26it's a table that wants to store kind of
  570. 25:28the parent or the base
  571. 25:30and also all its children in one row
  572. 25:39and the thing about it
  573. 25:42is that you can see it when you see rows
  574. 25:46which have either pattern or unpatterned
  575. 25:49columns that are always null for some
  576. 25:52rows and not null for others
  577. 25:55and they interleave with rows that are
  578. 25:58null for others but not for some
  579. 26:02okay it's hard to say it in English
  580. 26:04let's look at an example
  581. 26:08here we have a table of a catalog item
  582. 26:11a catalog item in my catalog has a SKU
  583. 26:14SKU
  584. 26:17something a code that represents that in
  585. 26:20my company
  586. 26:21a name every catalog item it's a shirt
  587. 26:23it's pants it's something
  588. 26:25and it has numeric size and letter size
  589. 26:28and if I looked at values for this table
  590. 26:30I probably would see that I have you
  591. 26:34know School ABC T-shirt size m
  592. 26:39and size M will have numeric size as
  593. 26:43sorry letter size populated in numeric
  594. 26:46size null
  595. 26:48versus I'll have you know pants with
  596. 26:52size 32 and
  597. 26:55um then I'll have the letter size null
  598. 26:57and the name so I can kind of look at it
  599. 27:00and see okay well the generalization
  600. 27:03here is that I have a table and there's
  601. 27:05a generality that all items have a
  602. 27:09school and a name
  603. 27:12but then I have some properties some
  604. 27:15columns that are valid for some stuff
  605. 27:17but not other and that's because I have
  606. 27:21products that are inherently different
  607. 27:23in the real world in the real world I
  608. 27:26find a shirt and it has an m on the back
  609. 27:28or I have a shirt or a top that has a
  610. 27:32size numeric on the back and they're
  611. 27:34kind of different they're cut different
  612. 27:36they're manufactured different they're
  613. 27:38aimed at different people
  614. 27:40so they are really different
  615. 27:42but I made them live together in one
  616. 27:45table
  617. 27:50so the way to kind of fix this
  618. 27:53is to say well I have a catalog item I
  619. 27:56still want to be generic there could be
  620. 27:58category catalog items corresponding to
  621. 28:00different uh things in the real world
  622. 28:03but then I have
  623. 28:06my numeric size catalog items and I
  624. 28:08shortened the name of the table here but
  625. 28:11those are numeric sized things
  626. 28:14and they have a numeric size
  627. 28:16and then I have a letter size
  628. 28:19and that lives in a different table
  629. 28:22so I'm not going to have null in the
  630. 28:24letter size ever
  631. 28:26and catalog item that happened to be
  632. 28:28letter sized will have a relationship to
  633. 28:31the stable and if I join it it will come
  634. 28:33out not null and vice versa and if I
  635. 28:37ever wanted a view that joined both of
  636. 28:39them or all three tables then I would
  637. 28:42have a flat thing but I will have it in
  638. 28:44different columns and I will know what
  639. 28:46to expect because I did this
  640. 28:49right I know very easily that this is
  641. 28:53um an item that has a letter size
  642. 28:55because it will have a school and a
  643. 28:57school for letter size dot school and a
  644. 28:59letter as letter size dot letter size
  645. 29:02coming back in my joined uh expression
  646. 29:05to show me what it is so the database
  647. 29:09doesn't have to think hard if it was
  648. 29:11more like it was on the left I will need
  649. 29:14to expose logic
  650. 29:18um everywhere to tell if this row
  651. 29:20happens to be
  652. 29:22wanting to represent things in one way
  653. 29:24or another or I will have to package it
  654. 29:26as an OPEC data type that's where people
  655. 29:28do type as string and just says oh I'll
  656. 29:30just do size and it'll be a VAR binary
  657. 29:33and let the application worry about it
  658. 29:36well great but then what if you want to
  659. 29:39sort Shirts by size
  660. 29:42well you know your size 30 40 will sort
  661. 29:46correctly Maybe
  662. 29:47or maybe it looks graphically and
  663. 29:49incorrectly and surely you know
  664. 29:53SML XL double XL all of those uh extra
  665. 29:57small will sort weirdly
  666. 30:00so it's just not good for anyone really
  667. 30:03to to do OPEC or to have these nulls
  668. 30:05either way kind of messes you up
  669. 30:10onwards
  670. 30:16um
  671. 30:17this one is about abnormal form which
  672. 30:22means I failed to uh do my process for
  673. 30:27storing things atomically and in their
  674. 30:30proper tables
  675. 30:34so I have my table enrollment here
  676. 30:37and enrollment in my university has
  677. 30:41people with a first name and a last name
  678. 30:44and I place uh
  679. 30:47I have a placeholder for the scores for
  680. 30:50the exams uh and uh you know the course
  681. 30:55belongs to a certain major no it's not
  682. 30:57the course it's the professor and
  683. 31:00there's a course itself what the course
  684. 31:02code is and a teacher and assistant and
  685. 31:04stuff like that so A bunch of things
  686. 31:06smell here let's kind of go through them
  687. 31:09the first thing is I'm limited to the
  688. 31:12number of exams that can occur in a
  689. 31:14semester or a quarter or whatever system
  690. 31:16right because I chose to Pivot this and
  691. 31:20just put the exams right there so where
  692. 31:22should it have been
  693. 31:27a different table that's right
  694. 31:29and then if exam final exam hasn't
  695. 31:33occurred yet there will be no row it's
  696. 31:35not like I have a placeholder because I
  697. 31:37know I have it it just doesn't exist at
  698. 31:40this point
  699. 31:45um in this I will have nulls often
  700. 31:47because I fixed the columns which means
  701. 31:51that as time goes by I will start
  702. 31:55filling in the exam scores and if
  703. 31:57somebody missed an exam it will forever
  704. 31:59be no
  705. 32:01also some of my courses uh just have a
  706. 32:04teacher a professor some of them have a
  707. 32:07teaching assistant but that means that
  708. 32:10rose that there is no teacher assistant
  709. 32:12forever will have null in there so we
  710. 32:15talked about that that's silly
  711. 32:17we have a fixed faculty assignment which
  712. 32:20means for extremely uh large classes I
  713. 32:24might not be able to accommodate another
  714. 32:25ta and other teacher assistance
  715. 32:29um I might be duplicating data when I
  716. 32:32see these kind of things there's usually
  717. 32:34another table which represents the
  718. 32:36teacher elsewhere so instead of using
  719. 32:39reference properly to just say well
  720. 32:41here's a teacher go join if you need
  721. 32:43their name or whatever the primary key
  722. 32:45was
  723. 32:46um
  724. 32:47that that is probably duplicating data
  725. 32:50which means at some point There's issues
  726. 32:52of maintaining consistency between this
  727. 32:55table and the other one
  728. 32:58um and you're trying to predict the
  729. 33:00future you're trying to predict that
  730. 33:02this you know
  731. 33:03student will actually complete the
  732. 33:05course
  733. 33:06you're trying to predict that you will
  734. 33:08need to accommodate teachers assistance
  735. 33:10you're trying to do all kinds of things
  736. 33:11all kinds of assumptions that may not
  737. 33:13actually Bear in reality
  738. 33:22so the effects of that
  739. 33:25you will have sparse columns that's the
  740. 33:28ones with nulls that may forever be null
  741. 33:31may just populate over time it can
  742. 33:35decrease your flexibility in case I
  743. 33:37wanted to play with how many Tas and
  744. 33:39things happen
  745. 33:41it may negate the join engine the engine
  746. 33:46join optimizations where
  747. 33:51um
  748. 33:52I have um the the query optimizers know
  749. 33:57how to look at the statistics of indexes
  750. 33:59and see which query it should do first
  751. 34:02if I joined you know all of my students
  752. 34:04into courses it knows which one has more
  753. 34:08rows and knows how to do it faster if it
  754. 34:11gets right statistics but when you have
  755. 34:13null columns it doesn't
  756. 34:16it just has to kind of guess as to which
  757. 34:19of the values in the index you're going
  758. 34:21to hit and it's difficult for it to do
  759. 34:24without actually scanning the index
  760. 34:27and as a result you will have indexes
  761. 34:30that need to contain references to all
  762. 34:33of
  763. 34:34um the values in the columns so even if
  764. 34:38you have nulls some engines will still
  765. 34:40keep index keys on it or reference to
  766. 34:43rows with the null value and that
  767. 34:47increases the overall index size
  768. 34:49whereas if it was in a side table and
  769. 34:51there's only you know 10 Tas in the
  770. 34:53whole school well the index size will be
  771. 34:5610 entries
  772. 35:00and depending on your engine locks and
  773. 35:03things like that will also creep up so
  774. 35:06as you update tables that are
  775. 35:08multi-entity or that are of abnormal
  776. 35:11form
  777. 35:12you will find that right lock
  778. 35:15contentions at a higher level like at
  779. 35:18the table instead of just Roblox will
  780. 35:21start creeping up because everything you
  781. 35:23write is into the table whereas if you
  782. 35:25just wanted to add a teacher's assistant
  783. 35:27in a teacher's assistant table you're
  784. 35:30locking there so now you made all the
  785. 35:33locks kind of
  786. 35:34compete in this table space
  787. 35:42so that's about it and the queries
  788. 35:44complex Point uh is is kind of similar
  789. 35:47here and the multi-ended table which is
  790. 35:51um
  791. 35:52that queries need to bifurcate them I
  792. 35:55querying here because I'm trying to hit
  793. 35:56the teacher and what they teach or the
  794. 35:59student or something and they need to
  795. 36:01deal with the null ability of certain
  796. 36:03fields and say is this person not doing
  797. 36:06this exam or the exam hasn't passed yet
  798. 36:09we don't know
  799. 36:11the exam date hasn't arrived yet sorry
  800. 36:13so logic will creep in and be spread
  801. 36:17everywhere
  802. 36:20this is my attempt at humor
  803. 36:24thank you thank you for your grace on
  804. 36:27this
  805. 36:28um let's talk keys let's talk references
  806. 36:32um so in the world of keys
  807. 36:37there's what's called a natural key and
  808. 36:40a natural key is something that I can
  809. 36:42see in the real world
  810. 36:44so a natural key whatever I observe in
  811. 36:48the outside world in my model
  812. 36:50it exists in the model then it could be
  813. 36:52natural if it doesn't exist in a model
  814. 36:55it is probably not natural
  815. 36:58now natural doesn't mean
  816. 37:00that it's always non-assigned so if I
  817. 37:04have an agency that issued the iso
  818. 37:06two-letter code
  819. 37:08effectively it's a natural key of
  820. 37:11countries
  821. 37:12because it's part of a real business
  822. 37:15world it's something that an authority
  823. 37:18took over and it might be an authority
  824. 37:20of mine right I may be Twitter and I may
  825. 37:23be issuing or allowing for user names or
  826. 37:26handles or whatever system we have and
  827. 37:29that becomes a natural key because I
  828. 37:32manage it it's a thing so if it's for if
  829. 37:36it's a thing then it still kind of
  830. 37:39belongs in the natural key part of
  831. 37:42things most importantly it's meaningful
  832. 37:45and then it's part of the model
  833. 37:48it exists outside of my database
  834. 37:52artificial keys
  835. 37:54are meaningful
  836. 37:56they're known
  837. 37:57in the real world but they're kind of
  838. 38:00foreign to The Entity itself so
  839. 38:03countries in a domain of country in if I
  840. 38:06my entity was country that's a natural
  841. 38:09key but if it's me and my citizenship
  842. 38:12my citizenship is not me
  843. 38:15I am a person I'm attached to a
  844. 38:18citizenship it's foreign to the me It's
  845. 38:21associated it's still it's artificial
  846. 38:24but it's still observable in some way
  847. 38:26shape or form associated in the real
  848. 38:29world
  849. 38:30and now we go a little further in the
  850. 38:32rabbit hole don't slip and fall like the
  851. 38:34guy in the icon we have exposed locators
  852. 38:38and exposed locators are things that are
  853. 38:40in the database but not in the real
  854. 38:43world
  855. 38:45so those are primary keys
  856. 38:47let's say something that's a row ID an
  857. 38:54exposed row ID so like an identity
  858. 38:56column uuid that I assigned as a primary
  859. 39:01key as something a sequence those are
  860. 39:04things that are meaningful only to the
  861. 39:06database engine
  862. 39:07but I can't go up to a person and say oh
  863. 39:11year one two three four yeah yeah
  864. 39:14like there's no I like Pat him down
  865. 39:16there's no one two three four anywhere
  866. 39:18in the pockets there's just doesn't
  867. 39:19exist it's just an artifact of the
  868. 39:21database
  869. 39:23which means a lot of times it's also an
  870. 39:25artifact of that database instance like
  871. 39:28on that machine it's not everywhere
  872. 39:31which means I will have drift in other
  873. 39:33environments and things like that if I
  874. 39:35try to replicate I might have collisions
  875. 39:37if it was generated by two different uh
  876. 39:40systems things like that
  877. 39:43and those are exposed locators the
  878. 39:45exposed part here is that it's visible
  879. 39:47meaning I can somehow interact with it
  880. 39:50from my program this is a worse class
  881. 39:52which is the real surrogate key
  882. 39:56and these are ones that are not exposed
  883. 39:59so as you can imagine internally
  884. 40:01databases have identifiers for the
  885. 40:04blocks or for the row or things like
  886. 40:07that that are not even exposed to the
  887. 40:08programmers
  888. 40:09and some systems kind of let you use
  889. 40:12them by using special functions saying
  890. 40:14hey which version of this row do you
  891. 40:18have and it will give you a long ugly
  892. 40:21number and says this is you know storage
  893. 40:23related
  894. 40:24so that's very crusty stuff don't use
  895. 40:27that ever for uh primary keys
  896. 40:34so using meaningless Keys is the error
  897. 40:37here if you're using meaningless Keys
  898. 40:40things that don't participate in the
  899. 40:42real world
  900. 40:43either either being artificial or being
  901. 40:46just not part of the real world not
  902. 40:48natural in any way shape or form
  903. 40:53you are really
  904. 40:55um
  905. 40:56making everything more complicated
  906. 41:00um the number of joins you'll need to do
  907. 41:02let's say I have country ID 3 on my UI I
  908. 41:05can't say what this country ID is
  909. 41:09and Dora Angola I I forget but you know
  910. 41:11I I don't know right
  911. 41:14if I ever want the country code or if I
  912. 41:17ever want its name I would have to join
  913. 41:19to another table in order to get it if
  914. 41:21you use natural keys
  915. 41:23and my natural key say is this iso2
  916. 41:26letter code or the name of the country
  917. 41:28or ISO 3 then it's always there in my
  918. 41:31column already it already answers this
  919. 41:34question and if I wanted to filter I
  920. 41:36could filter through this yes sir
  921. 41:42yeah so there will be an impact in the
  922. 41:45impact on the change of the natural key
  923. 41:47will be judged by how we look at the
  924. 41:51impact of change so would that be a type
  925. 41:55change
  926. 41:56no it would be a domain change right it
  927. 41:59would be a
  928. 42:01change in the value Universe of that
  929. 42:05domain and in case that it's additive
  930. 42:08it's kind of similar to
  931. 42:10just adding a column that nobody used
  932. 42:13before and in case it's a change because
  933. 42:15it's primary key I think the gentleman
  934. 42:18is hinting at the fact that primary Keys
  935. 42:21need a property of immutability or rare
  936. 42:24changiness and that would have cascading
  937. 42:27effect which means it's harder yeah but
  938. 42:30harder does not mean
  939. 42:32don't ever do it harder means what is my
  940. 42:35main use case scenario for 99 of the
  941. 42:38time right
  942. 42:40um yeah so good point and I will judge
  943. 42:44it by the effort the pain it will cause
  944. 42:46me in the future the thing is
  945. 42:50I always have to join always always
  946. 42:52always always
  947. 42:54when I use a circuit key or exposed
  948. 42:58identifier
  949. 42:59I always have to do it so it's permeated
  950. 43:01through the whole thing
  951. 43:04and I said oh well they're using
  952. 43:06identity column that's fine right but
  953. 43:10everywhere in my joins everywhere join
  954. 43:12join join join join join and I'm like oh
  955. 43:14that's okay like oh my God there's a new
  956. 43:17ISO letter code or a country split
  957. 43:19happens
  958. 43:20it's like happens once once in five
  959. 43:23years
  960. 43:25it's not everywhere yeah it affects a
  961. 43:27lot of things but
  962. 43:28so
  963. 43:30where where am I going to have more pain
  964. 43:32that's kind of my question
  965. 43:35I'll take more questions later let me um
  966. 43:37continue on here
  967. 43:39um so it increases the number of joint
  968. 43:42tables great example by the way
  969. 43:44increases the number of indexes because
  970. 43:47now because I have joins every foreign
  971. 43:50key will need an index on the
  972. 43:53referencing table
  973. 43:55so it will increase that increase the
  974. 43:58number of objects because I will need
  975. 44:00that index I will need that extra table
  976. 44:03it may be sometimes I can have a domain
  977. 44:07represented already there
  978. 44:09so what if country code is used for
  979. 44:12addresses and used for citizenships
  980. 44:16do I need another table to just say oh
  981. 44:19my God these are country codes I better
  982. 44:22have a table for country codes
  983. 44:24or can I use a constraint that says hey
  984. 44:28in this country we only allow this array
  985. 44:31of items and use a check constraint or
  986. 44:33use something else another mechanism to
  987. 44:36enforce that domain and not use domain
  988. 44:39tables it's also possible
  989. 44:46um the clustering indexing efficiency
  990. 44:48has to do with
  991. 44:51with the exact engine so SQL server has
  992. 44:53this thing called the clustered index
  993. 44:56other databases don't quite do it this
  994. 44:59way so uh your mileage may vary there uh
  995. 45:03what would happen is when you're issuing
  996. 45:06sequences uh for the primary key when
  997. 45:10you're writing each right by definition
  998. 45:13is just one number higher which means
  999. 45:15you kind of right into the table at the
  1000. 45:18end of the table and if you're updating
  1001. 45:20it frequently that creates a hotspot
  1002. 45:23um
  1003. 45:24other Technologies might have other
  1004. 45:26Effects by this so
  1005. 45:28um it kind of this is a place where you
  1006. 45:31want to really learn about your specific
  1007. 45:33database and how these things behave
  1008. 45:35speaking of which that's the next slide
  1009. 45:38is sequential primary key auto-generated
  1010. 45:41keys and sequences are surrogate Keys
  1011. 45:46sequences are not meaningful in the uh
  1012. 45:49real world they're just invented things
  1013. 45:52that I somehow glued to my object and
  1014. 45:56because of that they suffer all of the
  1015. 45:58things we already discussed they're hard
  1016. 46:02to migrate among systems so that
  1017. 46:06happened to me a lot where on day one
  1018. 46:08you're in developer land on week two
  1019. 46:10you're in production yeah we
  1020. 46:13threw things in production after two
  1021. 46:15weeks
  1022. 46:16um
  1023. 46:17and then you know on year three we want
  1024. 46:21to simulate all the real problems we
  1025. 46:23have in production so we asked the ddbas
  1026. 46:26hey bring us back all the data from
  1027. 46:28production into uat or some area in
  1028. 46:31order for us to simulate and run our
  1029. 46:34software on real data because our
  1030. 46:36backend system as developers don't have
  1031. 46:39all this data in some of the conditions
  1032. 46:41and things we want to check is on a
  1033. 46:43variety of real world data
  1034. 46:45but then we kind of have to keep
  1035. 46:47resetting everything according to
  1036. 46:50production sanitize things like that
  1037. 46:52because there's collision with those
  1038. 46:54keys and when you have more than one
  1039. 46:57system then these keys that are
  1040. 47:00meaningless migrate into other systems
  1041. 47:03and they're not in sync anymore
  1042. 47:06because this you know person's country
  1043. 47:08ID says oh you know give me a list of
  1044. 47:12this country ID and another system and
  1045. 47:14the other system that country ID has
  1046. 47:16already changed because it's meaningless
  1047. 47:18it now collides with a different value a
  1048. 47:23different row altogether
  1049. 47:25so it's harder to keep in sync
  1050. 47:27um hotspot risks we spoke about and the
  1051. 47:32drift among environments can cause a lot
  1052. 47:35of
  1053. 47:37a lot of havoc on its own also
  1054. 47:40discourages schema migration so that
  1055. 47:44will come up in an later slide but I'll
  1056. 47:47talk a little bit about schema
  1057. 47:48migrations
  1058. 47:51so sequential primary keys are
  1059. 47:55essentially exposed locators
  1060. 47:58most people don't talk about the
  1061. 48:00difference between exposed locators and
  1062. 48:02surrogate keys so we'll call it circuit
  1063. 48:05key to adhere with the world
  1064. 48:08so what I want from a primary key I want
  1065. 48:11it to be
  1066. 48:12familiar I want it to be something that
  1067. 48:15somebody knowing the domain will say oh
  1068. 48:17yeah I get this
  1069. 48:20right an email address a username fine
  1070. 48:23sometimes a number is okay if that
  1071. 48:25number means something maybe it's your
  1072. 48:27ID number national ID something like
  1073. 48:29that it's okay
  1074. 48:31you want it to be stable
  1075. 48:33as a gentleman stated
  1076. 48:36um if things change what then
  1077. 48:39Well yeah if things change we'll need to
  1078. 48:42make changes the question is how rare is
  1079. 48:45it so when we say it's stable we don't
  1080. 48:48mean immutable forever we mean mostly
  1081. 48:51immunable
  1082. 48:53uh so mostly immunable means that
  1083. 48:55sometimes it will change on their very
  1084. 48:58rare condition
  1085. 48:59and then we'll have to deal with it most
  1086. 49:02relational databases also a lot of the
  1087. 49:05nosql databases
  1088. 49:07require you to keep to require not
  1089. 49:10require impose that the primary key is
  1090. 49:13immutable
  1091. 49:15those that support transactions allow
  1092. 49:18you to change that value under a cover
  1093. 49:20of a transaction
  1094. 49:22which means you basically delete the old
  1095. 49:24row insert a new row in its place with a
  1096. 49:27change value under one transaction cover
  1097. 49:32the operation can be long running if
  1098. 49:34there's a lot of dependencies or pretty
  1099. 49:36short but in any event we expect that it
  1100. 49:40is rare
  1101. 49:41so meaningful uh rarely changes
  1102. 49:46and convenient it's simple and compact
  1103. 49:50so don't ask me about how to represent
  1104. 49:54people because it's a first name first
  1105. 49:56name last name middle oh there's a
  1106. 49:58collision what else can I do can I Pat
  1107. 49:59people down do I put their DNA sequence
  1108. 50:01into the ID no that's a tougher one to
  1109. 50:06answer but typically it comes with
  1110. 50:08something I'm making a system for the
  1111. 50:11immigration services okay it has to do
  1112. 50:13with IDs it has to do with some other
  1113. 50:16external IDs that I can attach to it and
  1114. 50:19make it as something right or I make my
  1115. 50:22own I say hey your email address is you
  1116. 50:24I don't care what your name is your
  1117. 50:26email address is you and you are the
  1118. 50:28recipient of all of those change
  1119. 50:30passwords so this is you for all
  1120. 50:33intensive purposes
  1121. 50:34or a username or something like that and
  1122. 50:36then we don't want it to be too many
  1123. 50:38elements we want it to be somewhat
  1124. 50:40compact so it's convenient we want it
  1125. 50:43simple
  1126. 50:43so we don't have to deal with a lot of
  1127. 50:46logic to have multiple you know 10
  1128. 50:48column primary Keys kind of gnarly and
  1129. 50:51it appears again and again and again in
  1130. 50:53all your queries so we want it as simple
  1131. 50:55as possible
  1132. 51:01and now we switch abruptly to not
  1133. 51:05talking about the database so much but
  1134. 51:07talking about development and
  1135. 51:08development practices
  1136. 51:11and this is where orm comes into play
  1137. 51:14and
  1138. 51:15as a developer I love orm
  1139. 51:19I love the orm idea the first time I saw
  1140. 51:21it
  1141. 51:24um then I went to production
  1142. 51:28so the trouble with orm is that tables
  1143. 51:31are not classes
  1144. 51:32tables are the language that proprietary
  1145. 51:35SQL language that describes the schema
  1146. 51:37which has to do with the data layout
  1147. 51:39which the engines are then optimized to
  1148. 51:42deal with an answer for
  1149. 51:44but they're not classes
  1150. 51:47in a class I don't have pointers to
  1151. 51:49other things like foreign Keys it's just
  1152. 51:51a class has properties it's all in
  1153. 51:54memory as some contiguous something
  1154. 51:57typically
  1155. 52:02and the database is not the repo pattern
  1156. 52:05and orms kind of encourage the repo
  1157. 52:07pattern which is like oh I have an
  1158. 52:11entity like invoices
  1159. 52:13okay well that's my class invoice and
  1160. 52:15the class has an array of invoice items
  1161. 52:18each one has a school and a quantity
  1162. 52:21maybe I copy in the title of the name or
  1163. 52:24something who cares and it also has a
  1164. 52:26customer
  1165. 52:27which is a reference to you know
  1166. 52:29something so what the orm will happily
  1167. 52:32do is just go and spider all of the
  1168. 52:34tables because
  1169. 52:35you know School items items are many for
  1170. 52:38one invoice I have a table and I have a
  1171. 52:40relationship and it will Traverse it and
  1172. 52:42do the whole thing and and it will
  1173. 52:44produce just gnarly uh queries in order
  1174. 52:48to do this and then when I say okay on
  1175. 52:50top of this a repo essentially what I'm
  1176. 52:52saying is suck up all of this data into
  1177. 52:55memory and let me in memory iterate it
  1178. 52:58as if it's some kind of loop well that
  1179. 53:02will be either chatty like get me the
  1180. 53:04next one the next one the next one with
  1181. 53:06all the joins or it will be chunky like
  1182. 53:08load everything into memory and let me
  1183. 53:10do it into memory in memory either one
  1184. 53:13of those is a heavy operation
  1185. 53:16and the database engine can't really
  1186. 53:18help you so it just gets gnarly's
  1187. 53:20queries executes them on your behalf and
  1188. 53:23tries to deserialize everything and then
  1189. 53:25the cost of serializing is also present
  1190. 53:29deserializing from the database
  1191. 53:31so I don't like the database repo uh
  1192. 53:35kind of mentality uh database is a repo
  1193. 53:38mentality that is imposed through using
  1194. 53:41an orm
  1195. 53:44you have a diminished benefit from the
  1196. 53:46orm in my experience in that you start
  1197. 53:50with you know oh Entity framework oh
  1198. 53:52forward generated schema or backwards
  1199. 53:54generator schema my DBA did a good job
  1200. 53:57let me just suck it in generate classes
  1201. 53:59either way this is great for week one
  1202. 54:04hey Nuri did you manage to start the
  1203. 54:06project oh yeah I have working code
  1204. 54:08now put it in production and for the
  1205. 54:11next five years you're gonna fight it
  1206. 54:13all of those decisions you have a static
  1207. 54:16class not a static you have a class that
  1208. 54:18got declared if you want to make any
  1209. 54:20changes it has cascading impact into the
  1210. 54:23database
  1211. 54:24because now you have to forward generate
  1212. 54:26tables and you have to do migrations
  1213. 54:28according to how the orm side vice versa
  1214. 54:32also same thing changes in the database
  1215. 54:34now you have to change the classes that
  1216. 54:37are essentially the dto of your database
  1217. 54:40right they are classes representing the
  1218. 54:43schema and it's not exactly the class
  1219. 54:45you wanted it's a class that got derived
  1220. 54:47because the orm said so
  1221. 54:50that's not how I like to live my life
  1222. 54:54you'll have concurrency issues because
  1223. 54:56the repo model the repo mentality makes
  1224. 54:59you think of the invoice as a single
  1225. 55:01thing but then if you want to change the
  1226. 55:03invoice you're not thinking about just
  1227. 55:05changing the element
  1228. 55:07and if you change just a line item and
  1229. 55:09change the quantity
  1230. 55:10the object that was in memory that was
  1231. 55:13the whole invoice and mapped to a class
  1232. 55:14that you have at your disposal are not
  1233. 55:17in sync
  1234. 55:18so you have to do things like
  1235. 55:19concurrency tracking change tracking
  1236. 55:22doing all kinds of back and forth to see
  1237. 55:25if it changed before you write it all
  1238. 55:28kinds of stuff like that which would not
  1239. 55:30be necessary if you went directly
  1240. 55:34and finally
  1241. 55:37um it's once established not finally I
  1242. 55:40kind of mentioned it once you establish
  1243. 55:42the entity to class mapping it's it's
  1244. 55:45kind of costly to change it and it's
  1245. 55:47kind of opaque to change it you make
  1246. 55:49these changes and you know a lot of
  1247. 55:50things happen in the background and
  1248. 55:52chasing it everywhere becomes difficult
  1249. 55:56so Nuri do you really think RMS have no
  1250. 55:59place well now I'm a consultant of
  1251. 56:02course it depends
  1252. 56:06so the things I say maybe orms are
  1253. 56:08helpful
  1254. 56:09are in the arena of
  1255. 56:12connection management
  1256. 56:14it brings you some benefit that you
  1257. 56:16don't have to do it on your own hide
  1258. 56:19some connection pools or contains a
  1259. 56:21connection pooling and kind of instant
  1260. 56:24Singleton instance that you can deal
  1261. 56:26with or multiple injectable items that
  1262. 56:29map to the same underlying
  1263. 56:31infrastructure not the lousiest idea
  1264. 56:33maybe that's a useful thing it does the
  1265. 56:37codec work of mapping between the
  1266. 56:40tabular data format that came from The
  1267. 56:42Wire into SQL types and into c-sharp
  1268. 56:45types I like that that that's a good
  1269. 56:47thing right if I could get a bunch of
  1270. 56:49stuff a bunch of tables and
  1271. 56:51automatically marry them to my um
  1272. 56:54marry them to my to my classes I I kind
  1273. 56:58of like this but I really don't like the
  1274. 57:01command marshalling the fact that I have
  1275. 57:03to go through the orm just to call
  1276. 57:04stored procedures functions things like
  1277. 57:07that and personally it just makes no
  1278. 57:10sense to me you could use the driver the
  1279. 57:12driver actually does it not the orm so
  1280. 57:15use the driver directly the abstractions
  1281. 57:18it provides such as repo patterns and
  1282. 57:21stuff like that
  1283. 57:22seem nice but
  1284. 57:24you know after week two I usually just
  1285. 57:27fight against the orm instead of
  1286. 57:28enjoying it so that tells me it's not
  1287. 57:31that useful
  1288. 57:33and change detection concurrency uh
  1289. 57:36handling and all of that I just that
  1290. 57:37that is something that I really uh
  1291. 57:40resent every time I encounter it's just
  1292. 57:44not not fun
  1293. 57:47and then the last one
  1294. 57:49uh we'll talk about here number seven uh
  1295. 57:54is ad hoc ddl so the notion of uh going
  1296. 57:58and just adding a column by hand
  1297. 58:01uh that you know I've seen dbas do this
  1298. 58:04I've seen various degrees of of
  1299. 58:07responsibility around it the problem
  1300. 58:10with manual changes to ddl or creation
  1301. 58:13is that it's not very repeatable or not
  1302. 58:16reliably repeatable you can't automate
  1303. 58:19this you can't play this again in every
  1304. 58:22environment and you can't sometimes tell
  1305. 58:25what happened if you don't have a good
  1306. 58:27record of who made the action who
  1307. 58:30changed things how you're going to know
  1308. 58:33when Trouble Comes how come it was
  1309. 58:35working yesterday and not working today
  1310. 58:37like what is the change when did it
  1311. 58:39happen who did it for what purpose we
  1312. 58:41don't know any of this and the foregone
  1313. 58:43conclusion is well you know use
  1314. 58:46migration script
  1315. 58:48so you can use uh you know Flyway liquid
  1316. 58:52base whatever your system supports or
  1317. 58:54you love using uh if you're not using
  1318. 58:56any of those please read up and uh look
  1319. 59:00at it the nice thing about migration
  1320. 59:02scripts is you store them as files
  1321. 59:05the Frameworks themselves let you just
  1322. 59:08play it you can play it on demand many
  1323. 59:11of them support the notion of rollback
  1324. 59:13so if you made a mistake you can revert
  1325. 59:16having it in automation CI CD I'm sure
  1326. 59:20we've all talked about in the last 10
  1327. 59:22years so this is what enables you to do
  1328. 59:25CI CD with databases highly recommended
  1329. 59:31um
  1330. 59:31and that's about it
  1331. 59:34so my advice in summary is all just use
  1332. 59:38natural keys to the degree possible use
  1333. 59:41the database how it was intended to be
  1334. 59:44used which is store Atomic values
  1335. 59:47normalized to the degree possible
  1336. 59:49concise data types for what you're
  1337. 59:51trying to represent and not wishy-washy
  1338. 59:53things like Json and XML shoved in a
  1339. 59:56relational database
  1340. 59:57come to my later if you want to
  1341. 1:00:00talk about documents my mom will talk
  1342. 1:00:02later
  1343. 1:00:03orms not my favorite at all
  1344. 1:00:07and if you've ever had to fight your orm
  1345. 1:00:10and go below it and just hand it a
  1346. 1:00:12statement you know that the orm didn't
  1347. 1:00:15help you you know it
  1348. 1:00:16inside right
  1349. 1:00:19okay
  1350. 1:00:20so that is it I'll take questions we
  1351. 1:00:22have a couple minutes or we don't have
  1352. 1:00:25minutes
  1353. 1:00:28okay
  1354. 1:00:30I can't use natural Keys like a
  1355. 1:00:32meaningful Keys would you recommend
  1356. 1:00:35using minions so the question is and uh
  1357. 1:00:40don't feel obligated to sit down it's
  1358. 1:00:42past time here
  1359. 1:00:43um
  1360. 1:00:44in the case of natural if natural keys
  1361. 1:00:47don't work would I recommend using a
  1362. 1:00:50non-natural key so synthetic yes
  1363. 1:00:53uh exposed identifier or surrogate
  1364. 1:00:56surrogate
  1365. 1:00:58it's almost impossible to use pure
  1366. 1:01:00surrogate but
  1367. 1:01:02um I I would recommend against it in
  1368. 1:01:06many all cases in other words Invent
  1369. 1:01:08Yourself if if nobody else if there's no
  1370. 1:01:11Authority that lets you identify
  1371. 1:01:13something then you are the authority and
  1372. 1:01:16if you are the authority maybe own up to
  1373. 1:01:19it and become the authority on that like
  1374. 1:01:20that is what a school is Right a stop
  1375. 1:01:23stock keeping unit no other manufacturer
  1376. 1:01:25could tell me what the item number is
  1377. 1:01:28because their item numbers are private
  1378. 1:01:30to them I'm the big shop that sells from
  1379. 1:01:33many manufacturers and they could
  1380. 1:01:35Collide so I assigned it a stock keeping
  1381. 1:01:38unit which is a number on the Shelf of
  1382. 1:01:40how I keep it so I became the authority
  1383. 1:01:42to that otherwise I would have to say
  1384. 1:01:45galvanized screw you know M3
  1385. 1:01:49and I would not be able to distinguish
  1386. 1:01:53it so how do I distinguish disambiguate
  1387. 1:01:55it with a school that's completely
  1388. 1:01:57synthetic or with a dash manufacturer
  1389. 1:01:59number or with a something I become the
  1390. 1:02:02Authority for that and I store it
  1391. 1:02:09okay uh thank you so much
  1392. 1:02:12um
  1393. 1:02:13enjoy the rest of them

About this transcript

This page contains the full transcript of Design Good Schemas - Get a Better Database - Nuri Halperin - NDC Oslo 2023 by NDC Conferences, generated from the public captions YouTube serves with the video. The transcript has 9,083 words across 1,393 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.

What you can do with it

Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to translate the transcript into 100+ languages.

Free YouTube transcript tool

YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, translation to 100+ languages, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.