【问题标题】:What is the best way to store and query a very large number of variable-length lists in a MySQL database?在 MySQL 数据库中存储和查询大量可变长度列表的最佳方法是什么?
【发布时间】:2015-08-01 03:33:24
【问题描述】:

也许通过一个例子可以更清楚地说明这个问题。假设我正在使用的数据集是一大堆(几千兆字节)可变长度的元组列表,每个列表都与一个唯一的 ID 和一些元数据相关联,我希望能够通过以下方式快速检索这些列表中的任何一个它的 ID。

我目前有两个或多或少这样设置的表:

TABLE list(
  id VARCHAR PRIMARY KEY, 
  flavor VARCHAR, 
  type VARCHAR, 
  list_element_start INT, 
  list_element_end INT)

TABLE list_element(
  id INT PRIMARY KEY, 
  value1 FLOAT, 
  value2 FLOAT)

要从数据库中提取特定列表,我目前执行以下操作:

SELECT list_element_start, list_element_end FROM list WHERE id = 'my_list_id'

然后我使用检索到的list_element_startlist_element_end 值来获取列表元素:

SELECT * 
  FROM list_element 
  WHERE id BETWEEN(my_list_element_start, my_list_element_end)

当然,这工作得非常快,但我觉得好像有更好的方法来做到这一点。我知道我可以在 list_element_end 中有另一个名为 list_id 的列,然后执行SELECT * FROM list_element WHERE list_id = 'my_list_id' ORDER BY id 之类的操作。但是,在我看来,拥有该额外列以及该列上的外键索引会占用大量不必要的空间。

有更简单的方法吗?

抱歉,如果以前有人问过这个问题,但我无法找到答案。如果可能的话,我还想在 Python 中使用 SQLAlchemy 来完成所有这些工作。

提前致谢!

【问题讨论】:

  • 为什么一个简单的连接不够?
  • 您可以使用 blob 来节省空间,但管理它们(修改、删除)会很麻烦。

标签: python mysql database sqlalchemy


【解决方案1】:

您可以将数组的每个元素标准化为一行。以下是 SQLAlchemy 中的声明式样式,它将为您提供具有风味等的“MyList”对象,然后元素将是每个“MyElement”对象的实际 Python 列表。在返回的元素列表中清除多余的 id 和 idx 可能会变得更加复杂,但这应该足够快。

此外,在上面,您混合了 varchar 和 int 作为主键,不确定这是否只是疏忽,但您不应该这样做。此外,在处理大型数据集时,请记住分块等选项。您可以使用 offset 和 limit 来处理较小的尺寸并进行迭代处理。

class MyList(Base):
    __tablename__ = 'my_list'
    id = Column(Integer, primary_key=True)
    flavor = Column(String)
    list_type = Column(String)
    elements = Relationship('my_element', order_by='my_element.idx')

class MyElement(Base):
    __tablename__ = 'my_element'
    id = Column(Integer, ForeignKey('my_list.id'))
    idx = Column(Integer)
    val = Column(Integer)
    __table_args__ = (PrimaryKeyConstraint('id','idx'), )

【讨论】:

  • 嗨 - 感谢您的回复。您是说 MyElement 中的外键位于“my_list.id”上吗?如果我将其保留为“my_element.id”,则会收到关于没有链接表的外键的错误。如果是这样,那么这是否会创建一个包含指向每个特定列表元素的列表 id 的指针的列,以及用于快速查找的相当大的索引?
  • 关系数据库就是这样设计的。这里没有额外的索引,每个主键只有一个索引(无论如何都是必需的)。不知道你怎么能做得比这更好。
【解决方案2】:

between 不是一个函数,所以我不知道你认为那里发生了什么。无论如何...为什么不:

SELECT e.* 
  FROM list_element e
  Join list l
   On l.id between e.my_list_element_start and my_list_element_end

或者我错过了什么

【讨论】:

    猜你喜欢
    • 2019-10-11
    • 2012-04-25
    • 1970-01-01
    • 2017-03-13
    • 2011-05-24
    • 2011-01-20
    • 2021-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多