Cloud spanner 最佳实践 INTERLEAVE 问题

Posted

技术标签:

【中文标题】Cloud spanner 最佳实践 INTERLEAVE 问题【英文标题】:Cloud spanner best practice INTERLEAVE questions 【发布时间】:2018-02-25 00:14:52 【问题描述】:

让我们以文档中定义的表格为例:

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 个表格 SingersAlbumsSongs专辑 INTERLEAVE 歌手表和歌曲 INTERLEAVE 歌手表> 和专辑

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

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

【问题讨论】:

【参考方案1】:

我想到了两个解决方案:

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

    选择singer.singerId、albums.albumId、songs.trackId 来自歌手左加入专辑 ONsingers.singerId = albums.singerid 左加入歌曲 ON albums.albumid = song.albumid

    有一张像这样的表:

表架构:

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 次大表扫描而不是 3 次,但我不知道这是否最好,因为服务器将在服务器之间拆分数据,所以我们将结束在拆分之间进行多项选择)。

您认为哪种解决方案效果最好,如果您有什么我想念的,请解释一下。

【讨论】:

【参考方案2】:

我建议使用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;

从没有相应行的子表/交错表读取返回空结果,因此需要 3 个单独的读取请求 -

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

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

虽然查询子表 - 这不会返回任何结果,因为该表没有 SingerId = 1 的歌曲:

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

没有结果。 查询未返回任何行。

PS - 不知道你在这里所说的“分裂”是什么意思 - “检索有关歌手的所有信息(如果可能,一次拆分)。”

【讨论】:

以上是关于Cloud spanner 最佳实践 INTERLEAVE 问题的主要内容,如果未能解决你的问题,请参考以下文章

Cloud Spanner 读取与 Cloud Spanner SQL API

Cloud Spanner - `SHOW TABLES` 的等效语法?

Cloud Spanner:拆分“太大”的含义

如何有效地与多个线程并行查询 google-cloud-spanner?

Google Cloud Spanner 和 Cloud SQL 有啥区别?

Google Cloud Firestore 与 Google Cloud Spanner 的区别?