Database Design for Google Calendar: A Tutorial
kb.databasedesignbook.com
kb.databasedesignbook.com
Would suggest instead of designing a schema at all, a calendar is a good example of a problem that might be far better implemented as a scan. Optimizing an iCalendar parser to traverse a range of dumped events at GB/sec-like throughputs would mean the above worst-case calendar could be scanned in single-digit milliseconds.
Since optimizing a parser is a much simpler problem to solve once than changing or adding to a bad data model after it has many users, and that the very first task involving your new data model is probably to write an iCalendar importer/exporter anyway, I think this would be a really great trade off.
The format shows its age - you can tell it was designed before XML/JSON were "hot".
“Meet me at high noon!”
Was never met with -
“High noon? What time zone?”
If that works for you, go for it.
The appropriate schemas are vastly different: a message like iCalendar should be simple and self-contained (leaving cleverness to the applications exchanging it), while a database like the article discusses should be normalized (nontrivial structures and queries aren't a problem).
My doctors calendar app vendor was pretty happy I found the root cause of their very occasional mystery appointment drift too.
New years is midnight, local time, wherever you are. Trust me.
(Actually there’s a famous missing person’s case related to a New Year’s party in New Zealand … I don’t think that timezones were part of what went wrong, but I can’t be sure.)
A single number is not enough to store a datetime.
I blame databases for only storing half of the data and leaving the other half to the environment.
or you can tell it was designed by people who care more about performance.
> or you can tell it was designed by people who care more about performance.
I doubt parsing iCal is significantly more performant than JSON for most use cases. In fact I can image it being less so in more cases than it is more so, and as close to the same as makes no odds in the vast majority of cases.
While it is true that dealing with json by hand is going to be more work than just importing an iCal library, I'm comparing apples to apples and suggesting dealing with json "by hand" is no more faff than dealing with iCal "by hand", and that dealing with either via a good library equally gives no benefit to iCal.
iCalendar is based on vCalendar, http://www.imc.org/pdi/vcal-10.txt - need to go to archive.org to see it, which shows Sept 1996.
from wikipedia, XML is listed as first published in Feb 1998, JSON is early 2000s.
edit: XML'd iCalendar, 2011 - https://datatracker.ietf.org/doc/html/rfc6321
JSON'd iCalendar, 2014 - https://datatracker.ietf.org/doc/html/rfc7265
In a real application you'd probably have some user accounts of some sort that are stored in a relational database already and then you'd suddenly have to scan for events in a directory that you then have to connect to those records in the database.
So there might be some specific set of applications where you are right, but there are specific things that a database is really good at, which would make it a really good choice. With the proper indices you'd probably get the same or even better throughputs, unless you come up with some clever directory structure for your events, which would in fact be the same as an index and only on one dimension whereas in a database you'd be able to create indices for many dimensions and combinations of dimensions.
So you are right, trade offs.
Even just something like: CREATE TABLE calendar(id, user_id, blob)
Also, in the context of web applications, you probably already have a database and probably don't have persisted disks on your application servers, which then adds complexity to the file based scenario. In which case using blobs is a perfectly fine solution indeed.
Still you are right that in many cases, let's say a desktop application, you are probably better off reading directly from tens of files on disk rather than having to deal with the complexity of a database.
The same applies to vector databases. I read an article a few months ago that spoke about just storing vectors in files and looping through them instead of setting up a vector database and the performance was pretty much the same for the author's use case.
- OP says to always store a timezone with each date, yours says to convert everything to UTC (I agree with OP)
- OP says to generate database rows for each event, yours says to not do that (I agree with yours)
Jon Skeet talked about this once. https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a...
What I take is convert everything to UTC is fine if it's historical data, even unix timestamp is fine. However for the future datetime, it's more complicated than that.
Inevitably the user will come back and say "oh, I want it monthly except this specific instance" or if it's a time based event "this specific one should be half an hour later". You could just store the exceptions to the rule as their own data-structure but then you need to correlate the exception to the scheduler 'tick' and if they can edit the schedule, well, you're S.O.O.L either way but I think having concrete occurrences is potentially easier to recover from.
To this day whenever I have to work with anything datetime related I dread it, it just does not click in my head for some reason
It is deceptively hard and requires excellent data modeling skills.
So last one I remember was how would you build a product table with coupons. Ok, so two tables right, no big deal. Well, we are going to need to keep a history right? So now I need to update and have datetimes for different products and coupons. And now I should think about how to do indexes on the tables, and gosh my join to get the discounted price is that a good way to do that? Most coupons only allow a person to use them once, how the hell am I going to implement that?
They probably just wanted the simple product + coupon table, but let me spin on it for quite a while like a madman.
To be clear, I think the ability to be your own data engineer is a great attribute as a data scientist. I just don't think it's reasonable to expect it: it's not part of the core job description.
I interpreted the question to be asking about "warehousing" moreso than just "laying out data", but I think I might have read too far into it.
How does the deliverable for this sort of analysis look? Do you have a link to some example documents (or maybe chapters in a book or whatever)?
Coincidentally, the guy who taught me this process just published a book about it, which he now calls "Agile with Blueprints": https://www.agilewithblueprints.com/
You can find a sample deliverable on GitHub here: https://github.com/AgileWithBlueprints/eRecipeBoxSampleApp/b...
Caveat: It's hard to convey the value of this approach because it shines most on complex systems that are hard to wrap your head around, and it feels like overkill when used on the kind of small project that one might want to start with. That said, I learned a lot of valuable lessons from it.
The term “anchor” feels kind of weird to me, but the explanation is so concrete/grounded (like an actual anchor) that I guess it works well enough.
The concept of defining the attributes via a question is solid, great way to get clarity quickly. Too often we jump to a minimal column/property name without defining what question we’re trying to answer, and thus not shaking loose any ambiguity in the mind of the customer(s).
> The term “anchor” feels kind of weird to me
This term was inherited from Anchor Modeling (https://en.wikipedia.org/wiki/Anchor_modeling). "Entity" is pervasive, but I don't want to use this word because it may bring unnecessary baggage and assumptions.
Also, this term is heavily overloaded: basically everything in CS is either an object or an entity, lol.
> The concept of defining the attributes via a question is solid, great way to get clarity quickly.
Thank you, this is an important confirmation for the validity of this approach.
Entity/object and “aggregate root” bring all sorts of complications/ambiguity.
The example you gave of a non-anchor (price was it?) was helpful to clarify.
Examples (and counter examples) are far easier for human brains to understand than “definitions”.
so often the example domain for these sorts of exercise is “a shopping cart website” —- and I find shopping websites such a poor example, because the specifics of how the shopping experience should work at a small Website are very custom to what is being sold, to whom, and why etc.
Other common domains when learning about databases
— “a book lending library” (I found this a good domain when I was learning, but people’s experiences of libraries are very different now…)
- a blog (posts, comments etc…) - but only fools like me write their own blog software now… (and or allow the public to comment? Yuck!)
I’ve written scripts that query outlook appointments and found that their handing of recurring appointments was very odd! Writing a query that simple asks “what am I doing today?” is far from a trivial exercise, as a consequence.
The choices and trade offs around storing every instance of a recurring appointment versus storing just the pattern plus the exceptions, has some pretty weird/nuanced implications. And I think the optimum approach really depends on the way I. Which the tool is used… which you don’t know until after the tool is used! (I guess that lends further proof that the most important aspect of software is that it’s open to being change in unexpected way… as any software worth writing will also need to be modified later.)
Cheers! Keep doing good work!
Assuming your timezone jumps forward one hour for daylight savings time and falls back one hour for transition to standard time...
When your time skips forward one hour, your 1 hour event may now be displayed as spanning two hours - the second hour will not be reachable/does not exist.
When your time falls back one hour, your 1 hour event may now show as spanning 2 hours or 0 hours.
Timezones are a man-made construct so don't hardcode values cause things will change...
Rather just focus on eliminating the Daylight Savings concept from the few localization that still use it, as they tend to cause the most confusion across timezones, especially when planning past an upcoming shift.
Timezones are not carved in stone. Prepare for that.
A location could go from a +1/-1 timezone as in most of USA/Canada to a fixed timezone with no transitions.
There are various ways to adapt, but the user-friendly way involves a lot more work in the app, especially if the app thought that timezone data wouldn't change.
Dealing with timezones will drive you mad, quickly.
The timezone inventors specified the timezone transitions would occur when most people weren't awake or affected - early in the day in the middle of a Saturday/Sunday weekend for USA/Canada.
But remote teamwork threw a wrench in that. 2AM Sunday meetings sounded unlikely unless your team needs to communicate with a team several hours ahead or behind and Sunday is a regular workday for one of the teams.
I guess you mean "implementing timezone logic yourself". other than that, the suggested approach (store everything in UTC) and translating to the relevant user timezone with a TZ database in the frontend is the way to go.
Dealing with timezones - including DST - properly is a must-have, no way around it. I live in a country that uses DST, a lot of Europe does that. If my calendar would be off by 1 hour half of the year, I'd consider it broken and seriously doubt the competence of its authors. This is the core domain of a calendar app! It would be like an email app that just silently drops every other email.
I'd love for us to ditch DST by the way, hate it every time. Its bad for the economy, its bad for our health, its bad for software.
> Rather just focus on eliminating the Daylight Savings concept from the few localization that still use it
Oh, certainly, change the laws and cultures of foreign states and peoples in order to simplify your code. Can you get them to just write everything in ASCII while you're at it?Arizona is Mountain Standard Time, no day light savings.
Navajo Nation, which overlaps state of Arizona, is MST with DST (since much of it is outside Arizona, and that's more common).
Hopi Reservation, which is fully contained inside both of Navajo Nation and Arizona, is MST with no DST.
You can drive 35 miles from Gray Mountain, AZ (non-reservation) through Tuba City (Navajo Nation) to Moenkopi (Hopi Reservation) and experience noDST->DST->noDST in just over half an hour.
Continue southeast for 100 miles to experience a bonus noDST->DST->noDST->DST->noDST->DST transition.
If you rely on your phone's automatic clock adjustment, best of luck!
Or do it in the app, of course.
As for API it makes a lot of sense to expose end time. If you for example are creating a calendar widget then it has start and end datetime for all events. With only duration available in the API output you know how to calculate the end time. More lines of codes for you.
Fetching from the API you would in most cases limit it to certain dates, for example next week. So now you suddenly do have to deal with start and end time. Not having it otherwise makes no sense.
Never had any developers ask for outputting duration in our scheduling API. It would be useful to include it but since no one have asked about it then I think having end time is more critical. https://developer.makeplans.com/#attributes-1
Requirement: Must be able to handle appointments that span a day, i.e. show all Sunday appointments when there's a party appointment that starts at 8PM Saturday and ends at 2AM Sunday, or in your data model, Saturday 20:00 for six hours.
Frankly speaking you could store all three (begin, end, duration) and just use whatever you need for different purposes. Just introduce a single point of entry/update that keeps alternative representations in sync.
Later I joined the company full time and discovered to my amazement that a contractor from a different company had removed the RRules in favour of creating and destroying instances of events on the fly. It had no/little fault tolerance so sometimes the script (which did other things that would sometimes fail) would fail to create new events. You'd have monthly recurring events with missing months.
I found it so frustrating that (after going through a lot of thought and research) that someone hadn't put anywhere near as much effort into removing mine. It took just a few weeks at that company to realise that the CEO expected the Engineering team to pump out features (that nobody used) at his will and, in the uncertainty of the job market, sadly I stayed there for 2 years.
Unrelated footnote: After Googling them, it's really sad to see what are blatantly fake reviews by the CEO on Glassdoor all written in the same style with nothing bad to say. I (and a bunch of other people I know who worked there) hated him, but the silver lining is that I wrote some of my best essays there. The CTO was hopeless too.
The control is highly customizable, with a lot of views to chose from, daily, monthly, yearly... but also resource views (you can book resources with custom groupings, by plugin, by the resource-ID, whatever...), define "plugins" on the data sources, what's the from- and to- columns, the title column, what's the resource (may be from a foreign key / 1:1 relationship or 1:N if it's from a "child" data source or from the same data source/table).
Furthermore I've implemented different appointment series, to chose from (monthly, weekly (which weekdays), daily...), which column values should be copied. Also appointment conflicts (or only conflicts if they book the same resource). You could also configure buffers before and after appointments where no other appointment can be.
That was a lot of fun and also challenge sometimes regarding time zones and summer/winter time in Europe and so on :-)
Will try to get my company to get a few copies of your book for each of our team member.
How about edits, changes of time and location, who's signed up and to which revision.
However, having your database not handle schema means your application must do it, there is no way around it. If you ask for an DayEvent and you get back something totally different, what do you do?
The rigidness in most NoSql (assuming some form of document store like MongoDB) comes from its inability to combine data in new ways in a performant manner (joins). This is what SQL excels at. That implies you need to design your data in exactly the way it is going to be consumed, because you can't easily recombine the pieces in different ways as you iterate your application. Generally you must know your data access patterns in advance to create a well behaved NoSql database. Changes are hard. This is rigid.
Thus, it actually makes more sense to go from sql to a nosql, as you gain experience and discover the data access patterns. The advantage of nosql is not flexibility, that is actually its disadvantage! The advantage is rather its horizontal scalability. However, a decent sql server with competently designed schema will go a very long way.
There's a very wide spectrum from having an evolvable document oriented data model with evolvable strongly consistent secondary indexes, transactions, aggregations, and joins to simplistic key/value stores like DynamoDB and Cassandra that do force you into a very much waterfall posture that I think you are spot on in pointing out.
Because PostgreSQL is unacceptably poor at HA/replication compared to MongoDB.
The way you use the term implies that you're referring to the type of data, but the term generally refers to the method used for storing the data.
This distinction is important because it leads to a circular reasoning dynamic: many of us are accustomed to storing the data in tabular form using a relational data model. But choosing to use that particular model to represent objects or entities or ideas does not make those objects or entities or ideas fundamentally relational data.
Also if you have non-traditional data structures e.g. document, star, graph, time series then storing them in a SQL database will cause you nothing but problems.
There are no black/white answers in tech. Always right tool for the right job.
They may use NoSQL in specific use cases, but certainly not exclusively. Using the right tool for the job is crucial; otherwise, you’re doing yourself and your product a disservice.
In this case, NoSQL database architecture and internals provide little to no advantage over relational databases. I can’t imagine building a calendar implementation with NoSQL. Some flexible parts of the event model might be stored as NoSQL, but in general? No way.
Edit: looks like I wrote my comment as you were editing yours. We agree :-)
Google Calendar is not implemented on top of a traditional SQL database but rather on top of Spanner which is more akin to a NoSQL database with a SQL front end.
You can choose a different approach if you want to use something like Cassandra, MongoDB or DynamoDB (or some other NoSQL solution). I am not an expert in all three, but I hope some day to write "alternative ending" for this tutorial and show how it can be applied in those environments.
Whatever database you choose, you still must do all the work of logical modeling (first six chapters) for your application. If you don't do that explicitly, you would have just to do that implicitly, intertwined with physical design and thus inherently more confusing.