连接到云中的数据库

新手上路,请多包涵

我在 S3 存储桶中有一个 SQLite 数据库 (110kb)。每次运行 Python 应用程序时,我都想连接到该数据库。

一个选项是每次我运行 Python 应用程序并连接它时下载数据库。 我想知道是否存在通过内存连接到 SQLite 数据库的方法,使用 S3FileSystemopen

我在 Python 3.6 中使用 SQLite3 库。

原文由 Joaquin 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 528
2 个回答

正如其他答案所表明的,您可能不想将 SQLite 用作云中的主数据库。

然而,作为一个有趣的副项目的一部分,我编写了一个 Amazon Athena 数据源连接器,它允许您 从 Athena 查询 S3 中的 SQLite 数据库。为此,我为 S3 编写了一个只读的 SQLite 接口。

SQLite 有一个 操作系统接口或 VFS 的概念。使用名为 APSW 的 Python SQLite 包装器,您可以为任意文件系统编写 VFS 实现。这就是我在我的项目中所做的,我在下面包含了实现。

为了使用它,您首先要注册 VFS,然后使用此实现作为驱动程序创建一个新的 SQLite 连接。

我应该注意到这根本没有优化,因此可能仍需要根据您的查询从 S3 读取完整的数据库。但在这个特定案例中听起来不像是个问题。

 S3FS = S3VFS()  # S3VFS defined below

# This odd format is used due to SQLite requirements
sqlite_uri = "file:/{}/{}.sqlite?bucket={}&immutable=1".format(
  S3_PREFIX,
  DATABASE_NAME,
  S3_BUCKET
)

connection = apsw.Connection(sqlite_uri,
  flags=apsw.SQLITE_OPEN_READONLY | apsw.SQLITE_OPEN_URI,
  vfs=S3FS.vfsname
)
cursor = connection.cursor()

一旦有了游标,就可以像这样执行标准的 SQL 语句:

 for x,y,z in cursor.execute("select x,y,z from foo"):
    print (cursor.getdescription())  # shows column names and declared types
    print (x,y,z)

_VFS 实施_(需要 APSW 库和 boto3 用于 S3 连接)

 import apsw
import sys
import boto3

VFS_S3_CLIENT = boto3.client('s3')

class S3VFS(apsw.VFS):
    def __init__(self, vfsname="s3", basevfs=""):
        self.vfsname=vfsname
        self.basevfs=basevfs
        apsw.VFS.__init__(self, self.vfsname, self.basevfs)

    def xOpen(self, name, flags):
        return S3VFSFile(self.basevfs, name, flags)

class S3VFSFile():
    def __init__(self, inheritfromvfsname, filename, flags):
        self.bucket = filename.uri_parameter("bucket")
        self.key = filename.filename().lstrip("/")
        print("Initiated S3 VFS for file: {}".format(self._get_s3_url()))

    def xRead(self, amount, offset):
        response = VFS_S3_CLIENT.get_object(Bucket=self.bucket, Key=self.key, Range='bytes={}-{}'.format(offset, offset + amount))
        response_data = response['Body'].read()
        return response_data

    def xFileSize(self):
        client = boto3.client('s3')
        response = client.head_object( Bucket=self.bucket, Key=self.key)
        return response['ContentLength']

    def xClose(self):
        pass

    def xFileControl(self, op, ptr):
        return False

    def _get_s3_url(self):
        return "s3://{}/{}".format(self.bucket, self.key)

原文由 dacort 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题