Cloud Spanner 最佳实践 INTERLEAVE 问题

Cloud spanner best practice INTERLEAVE questions

让我们采用文档中的 tables 定义:

CREATE TABLE Singers (
  SingerId   INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);

CREATE TABLE Albums (
  SingerId     INT64 NOT NULL,
  AlbumId      INT64 NOT NULL,
  AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId),
  INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

CREATE TABLE Songs (
  SingerId     INT64 NOT NULL,
  AlbumId      INT64 NOT NULL,
  TrackId      INT64 NOT NULL,
  SongName     STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId, TrackId),
  INTERLEAVE IN PARENT Albums ON DELETE CASCADE;

所以我们有 3 tables 歌手, 专辑 歌曲。 Table专辑交织歌手和table歌曲交织歌手专辑

我的问题是,如果我们想要搜索有关特定歌手的所有信息,如果歌手有专辑但还没有任何歌曲,我们可以在 table 歌曲中搜索吗?如果不是,检索歌手的所有数据(所有专辑和歌曲(如果他有的话))的最佳做法是什么。如果我们在歌曲中找不到任何东西,我想在 table 歌曲中搜索(因为歌手可以有专辑,但歌曲正在开发中)在 table 专辑中搜索,然后在歌手中搜索(因为即使是专辑可以在开发中),但我认为这不是最好的解决方案。

在我的例子中,进行查询的用户不知道歌手是否有任何歌曲或专辑,但想检索有关歌手的所有信息(如果可能,一次拆分)。

我建议使用 JOINs,可能会避免 3 次单独读取(类似的东西..)

select singers.singerId, albums.albumId, songs.trackId 
from singers left join albums ON singers.singerId = albums.singerid 
left join songs ON songs.SingerId = singers.singerId
order by singerId, albumId;

从 child/interleaved table 中读取没有相应的行 return 空结果,因此需要 3 个单独的读取请求 -

 
  select * from albums order by singerId, albumId;
  SingerId      AlbumId     AlbumTitle

   1            1           Total Junk  
   1            2           Go, Go, Go  
   .. more rows .. 
 

虽然查询 child table - 这个 return 没有结果,因为 table 没有歌手 ID = 1 的歌曲:

select * from songs where singerId = 1 order by singerId, albumId; 

没有结果。 查询没有 return 任何行。

PS - 不确定这里的 "split" 是什么意思 - "to retrive all the info about singer(in one split if possible)."

我得出了两个解决方案:

  1. 在这种情况下,我们有 3 table 扫描:歌手、专辑、歌曲。

    select singers.singerId, albums.albumId, songs.trackId
    来自歌手
    左加入相册开启 singers.singerId = albums.singerid
    左加入歌曲 ON albums.albumid = songs.albumid

  2. 有一个table喜欢:

Table 架构:

CREATE TABLE Singers (
  SingerId   INT64 NOT NULL,
  AlbumId INT64,
  SongId INT64,
  .
  .(informations about Singer, Album and Song)
  .
) PRIMARY KEY (SingerId);

所以我们会有这样的东西:

SingerId AlbumId  SongId  SingerName AlbumName SongName
   1                        Singer 1
   1        1                          Album 1
   1        1       1                           Song 1
   1        1       2                           Song 2
   1        1       3                           Song 3
   1        1                          Album 2
   1        2       1                           Song 1
   1        2       2                           Song 2
   1        2       3                           Song 3

通过 1 个查询,我们可以恢复所有关于 Singer 的数据。(我们有 1 个大 table 扫描,而不是 3 个,但我不知道这是否是最佳实践,因为服务器将再次将数据拆分为服务器,因此我们将在拆分之间以多个 select 结束。

您认为哪种解决方案效果最好,如果您有任何我遗漏的地方,请解释。