【问题标题】:Database design for dance-event tracklist storing舞蹈活动曲目列表存储的数据库设计
【发布时间】:2012-03-28 16:55:20
【问题描述】:

我正在用 Python 为一个简单的数据库编写一个简单的接口。该数据库是一个简单的数据库,它存储在哪个事件和哪个艺​​术家播放了哪些特定曲目。 Python 中的接口还不是问题,尽管数据库的设计是问题。我想出了以下几点:

--- EVENTS ---

CREATE TABLE events (
  id INTEGER PRIMARY KEY autoincrement,
  event_name TEXT NOT NULL,
  event_date TEXT NOT NULL,
  <list of tracklist-ids - foreign key?>
);

--- TRACKLISTS ---

CREATE TABLE tracklists (
 id INTEGER PRIMARY KEY autoincrement,
 artist TEXT NOT NULL,
 <list of track-ids - foreign key?>
);  

--- TRACKS ---

CREATE TABLE tracks (
 id INTEGER PRIMARY KEY autoincrement,
 trackartist TEXT NOT NULL,
 trackname TEXT NOT NULL,
 timesplayed INTEGER NOT NULL,
); 

我觉得这不合逻辑,我需要通过许多操作来从数据库中获取一些简单的东西,几个例子:

  • 获取艺术家 A 在 2006 年至 2009 年间播放的歌曲(曲目)列表:需要循环遍历“tracklists”表以获取艺术家 A 的每个 tracklistid,然后在“事件”中查找' 表(这已经很痛苦了,如何存储列表?)

  • 查找大多数时间播放曲目 A 的艺术家:循环遍历整个 'tracklists' 表并获取某种计数器来查找曲目 A 的 trackid

这可能会变得有点混乱,因为我在谈论很多不同的事情,但对我来说,我的数据库似乎可以设计得更好,还是我应该使用某种其他方法来处理这个程序数据库?我正在寻找一个基本的开始或提示/技巧,以使这个数据库更加高效和更好。我知道并非每次查找都可以很快,但对我来说这似乎不是很有效。另外,有没有更好的方法将列表存储到 SQL 数据库中,而无需将它们存储到字符串中?

【问题讨论】:

    标签: python database sqlite database-design


    【解决方案1】:

    我同意 Jens Schauder 的观点,即您想让 DBMS 担心过滤和计数,但我不同意表列表很好,因为 OP 提议的内容没有标准化。这不是一个小问题,因为它会阻止 DBMS 完成它的工作。

    此外,重要的是,我们的想法不是记录曲目播放次数,而是记录每次播放曲目。不同之处在于您要存储的是事件历史记录,而不是事件摘要。

    你想要的是看起来更像这样的表格:

    --- EVENTS --- 
    
    CREATE TABLE events ( 
      id INTEGER PRIMARY KEY autoincrement, 
      event_name TEXT NOT NULL, 
      event_date TEXT NOT NULL, 
    ); 
    
    --- ARTISTS ---
    
    CREATE TABLE artists (
      id INTEGER PRIMARY KEY autoincrement,
      artist_name TEXT NOT NULL
    );
    
    --- TRACKS --- 
    
    CREATE TABLE tracks ( 
     id INTEGER PRIMARY KEY autoincrement, 
     trackname TEXT NOT NULL, 
     artist_id INTEGER, 
     FOREIGN KEY(artist_id) REFERENCES artists(id)
    );  
    
    --- PERFORMANCES ---
    
    CREATE TABLE performances (
      id INTEGER PRIMARY KEY autoincrement,
      event_id INTEGER,
      track_id INTEGER,
      FOREIGN KEY (event_id) REFERENCES events(id),
      FOREIGN KEY (track_id) REFERENCES tracks(id)
    );
    

    此表结构为第三范式 (3NF),易于写入和查询。

    【讨论】:

    • 非常有趣,一些问题:如果我有 10 首同名曲目和三个不同的艺术家,它仍然会在曲目表中创建 10 个条目吗?这不是浪费空间吗?其次;您正在链接 event_id track_id,这有什么特殊原因吗?
    • @wvd - 链接 event_id 和 track_is 就像是在说“此曲目在此事件中播放”。关键是要记下发生了一些事情的事实。你计算事后发生的事情,而不是在你记录的时候。由于许多原因,这是一种更好的方法。关于你关于 10 首曲目和三位艺术家的问题,我不确定我是否关注你。你的意思是三位艺术家合作创作了 10 首不同的歌曲,还是你的意思是在一个活动中演奏了来自 3 位不同艺术家的 10 首不同的歌曲?你能举个例子(甚至是虚构的)吗?
    • 我理解你的想法。看起来很聪明。我在表here 中写了一些条目,唯一的问题是:艺术家可以制作和播放曲目。用你的方法,我永远不会说“艺术家 X 播放曲目 A 的次数最多”。
    • 编辑:我可以,我可以使用曲目名称作为完整曲目名称(包括艺术家),并使用外键 Artist_id 作为实际播放的艺术家的参考跟踪该事件。看起来不错!谢谢!
    • @wvd - 如果您的模型说曲目不“属于”艺术家,那么您只需将 Artist_id 和 FK 从曲目移至表演。然后,一首歌曲的每次表演都可能由不同的艺术家进行,您可以计算和比较哪些艺术家播放哪些曲目以及播放频率。
    【解决方案2】:

    乍一看,您的数据库看起来不错,唯一的例外是您没有将 id 列表存储在一个表中,而是从另一个表中返回对该表的引用。

    您描述的循环在 99% 的情况下是由数据库使用 'count' 和 'join' 完成的

    数据库在计数和查找方面非常出色且快速。

    如果您需要详细的帮助,您的 sql 语句应该是什么样子,请提出新问题。

    【讨论】:

    • 谢谢 :),很高兴看到性能是否比我认为的要好得多可以
    猜你喜欢
    • 1970-01-01
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-09
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多