6 Tony's answer was initially pretty near, but only worked for Native SQL Server Logins and not for Windows Authenticated SQL Server Logins. However, the general idea is the same.
5 An [exchange spill](https://docs.microsoft.com/en-us/sql/relational-databases/event-classes/exchange-spill-event-class) (`ExchangeSpillDetails`) occurs only in response to an [intra-query parallelism deadlock](https://docs.microsoft.com/en-us/archive/blogs/bartd/todays-annoyingly-unwieldy-term-intra-query-parallel-thread-deadlocks). SQL Server resolves the deadlock by forcing one or more of the exchanges (parallelism operators) to write its buffers to *tempdb*.
3 @SqlWorldWide answered the "why `[msdb]`" part of the question so I won't duplicate that here. But to answer the "why not `[master]`, `[model]`, `[tempdb]`" part of the question:
7 There look to be three different optimizer rules that can perform the `DISTINCT` operation in the above query. The following query throws an error which suggests that the list is exhaustive:
6 For completeness, another way to approach this problem is to use [OUTER APPLY](https://technet.microsoft.com/en-us/library/ms175156(v=sql.105).aspx). We can add an `OUTER APPLY` operator for each distinct value that we need to find. This is similar in concept to ypercube's recursive approach, but effectively has the recursion written out by hand. One advantage is that we're able to use `TOP` in the derived tables instead of the `ROW_NUMBER()` workaround. One big disadvantage is the query text gets longer as `N` increases.
6 Here is an attempt to emulate a repeated partial scan (similar to but not the same as a skip scan) using a recursive CTE. The aim - since we have no index on `(id)` - is to avoid sorts and multiple scans on the table.