Phantom vs Quill for Playframework (Scala) 和 Cassandra
Phantom vs Quill for Playframework (Scala) and Cassandra
我目前正在考虑在 PlayFramework 项目中使用 Cassandra 作为我的数据库。我一直在寻找反应式驱动程序,但我的选择似乎仅限于 Phantom 和 Quill。
我在 nosql 数据库方面的经验仅限于 MongoDB,而且我之前没有使用过任何 Quill 或 Phantom。
看看 comparison here ,似乎最终可能会在 Phantom 中编写更多代码。此外,使用 DSL 来描述模型似乎违反直觉(来自沉重的 hibernate/JPA 背景)——但这可能就是我。
我想知道是否有人可以提供实用的 advice/use 案例,其中一个案例 excel 和每个案例中需要注意的事项?
作为phantom的作者,我对phantom的设计目标把握得非常好。 Quill库网站上已有Quill和Phantom的对比,自然是偏向另一个方向。
Phantom 旨在成为应用程序层的完美选择,而 Quill 旨在成为最出色的字符串生成器,当您在 Cassandra 之上构建大型应用程序时,这不是一个非常有用的比较。
使用 phantom 的优点
关于类型安全以及 DSL 对 Cassandra 功能的改进程度,确实没有争议。 DSL 非常 "intimate" 了解您的数据结构,并提供对 Cassandra 功能的完整支持。它在编译时知道关于 Cassandra 什么是可能的,什么不是。
Quill 开发者认为 phantom 有更多的依赖关系,但这并不完全准确,因为其中大部分是可选的,包括 Play iteratees 和流支持等。得不到你想要的,就这么简单。
Quill 比较简单地指出:"You could extend Phantom by extending the DSL to add new features, although it might not be a straightforward process.",这有点不准确。作为游戏中的新玩家,Quill 在 Cassandra 功能支持方面是一个玩具,您会经常发现自己需要添加功能。 Phantom 无疑有其不足之处,但它是一个成熟得多的替代方案,并且需要扩展的次数要少得多。
对于更复杂的功能,我们已经在数天或数周内解决了大多数错误,但通常您可能需要的一切都已经存在,其中一些功能目前在 Quill 中找不到,这需要我小时连写下来。
我没有很强的 JPA 背景,但是 Cassandra 和 phantom 之间的映射是一个非常强大的层,因为它允许你自动生成 tables 直接来自映射 DSL。它还允许 DSL 在编译时完全模仿 Cassandra 的行为,它会知道关于您选择的主键等哪些查询是可能的,quill 根本没有这样的支持。
Phantom 具有非常强大的应用程序级抽象层,例如连接器、数据库、自动生成数据库,可以帮助您 运行 将应用程序投入生产。
Quill 背后的代码要复杂得多,虽然我会第一个高度赞扬它背后的工程能力,但当我认为用户友好时,这个故事就不太成立了还有。
Quill 尝试一次性完成更多工作。这是一个用于生成的迷你引擎,几年前 scalaquery 在决定完全专注于 SQL dbs 并放弃对其他任何东西的支持之前试图做的事情。它是现代 Slick 的前身,并使用类似的 QDSL 引用方法。
Quill 是一个泄漏的抽象。由于他们旨在支持更广泛的数据库,因此他们对数据库细节的特殊性的支持要差得多。示例如下:
从比较中最基本的例子中你读到:
val getAllByCountry = quote {
(country: String) => query[WeatherStation]
.filter(_.country == country)
}
}
到目前为止一切都很好,如果我们包含必要的映射代码,大概比虚幻的等价物更简洁。
select.where(_.country eqs country).fetch()
但让我们进一步探索。如果你想像这样获取一个国家怎么办?或者,如果您尝试获取 PagingState
信息怎么办?或者输入现有 PagingState
以在 UI.
上显示内容
这就是 Quill 至少在比较中未能让用户真正预览他们最终体验的地方。很自然地假设,无论何时您转到某个工具的页面,它都会将自己描述为同类中最好的工具,就像我们 phantom 背后的人所做的那样,但这绝不是全部故事。
为了更简洁,更酷的东西:
select.where(_.country eqs country).fetchRecord()
select.where(_.country eqs country).one()
部分 select 怎么样?
select(_.country, _.city).where(_.country eqs country)
Phantom 在使用 Cassandra 运行 时在语义上区分所有可能的事情,它首先尝试使用编译时技巧和领域知识来防止 运行 时间错误。你怎么能有 Quill 等价物?
此外,Quill 完全能够直接从 case class
.
生成查询
case class WeatherStation(
country: String,
city: String,
stationId: String,
entry: Int,
value: Int
)
object WeatherStation {
val getAllByCountry = quote {
(country: String) =>
query[WeatherStation].filter(_.country == country)
}
val getAllByCountryAndCity = quote {
(country: String, city: String) =>
getAllByCountry(country).filter(_.city == city)
}
val getAllByCountryCityAndId = quote {
(country: String, city: String, stationId: String) =>
getAllByCountryAndCity(country, city).filter(_.stationId == stationId)
}
}
但它缺乏关于您的架构的任何知识。如果国家不是主要国家的一部分怎么办?该查询无效,phantom 不会让你编译它,这只是最基本的例子。
Phantom 可以直接从 table 自动生成你的 CQL,它可以即时生成整个数据库,专业版甚至可以自动迁移 tables 并帮助你处理模式不一致,并为您提供非常先进的 UI 和监控界面,您可以在其中动态升级和降级模式。
缺点
Phantom 确实使 TypeCodec
之类的扩展变得稍微不那么冗长,但是从 phantom 2.9.0 开始,我们引入了一个非常强大的宏机制来编码 Cassandra 中的类型完全不依赖 TypeCodec
!
Phantom 在定义 table DSL 时需要最少的样板文件,并且本质上不能很好地共享 table 列。可以做到,但不是最美的代码,也不是最差的。
总体
- Quill 是一个非常好的软件,由非常有才华的人编写,对此毫无疑问。
- 严格来说,它比 phantom 在查询生成方面要好,有样板可以通过 QDSL 减少,而不能通过 EDSL 减少,如果我们打架谁是最精简的字符串生成器 Quill 获胜。
- 它在应用层是一个非常差的工具,对大多数人来说更不自然。 Slick 在某种程度上普及了这些概念,但是您想要作为应用程序生命周期一部分的一些最基本的功能并不能通过 QDSL 轻松解决,或者至少它还没有实现。
- Phantom 更加成熟,并且被广泛采用,拥有更多的资源和来自创始团队的投入、长期的路线图以及与 Datastax 的重要合作伙伴关系,这有助于我们掌握所有功能。
我们从 Quill 开始,然后由于 Phantom 的功能和易于更改而转向 Phantom。然而,我们 运行 在负载测试中遇到了严重的问题,发现它没有释放 CPU 线程和网络连接。我们在本地 mac machine 以及 AMI Linux 服务器的 AWS EC2 集群上进行了测试。本质上资源没有被释放,内存不足的异常将随之而来。如果这个问题得到解决,Phantom 就很棒了。就目前而言,我不能向任何拥有需要高性能的生产系统的人推荐使用 Phantom。
在生产的最后一刻,我们不得不更改所有代码并切换回 Quill,这让我很痛苦。
我已经用 Phantom 提出了一个问题,希望他们能尽快解决这个问题。随附的是一个项目,通过 运行 并排运行一个简单的 JSON/REST scala 项目来测试 Quill 和 Phantom 之间的负载。
https://github.com/yleun/cassandra-loadtest
如果 Phantom 可以解决这个内存不足的异常,它可能是一个优于 Quill 的数据库客户端,但就目前而言,它还没有准备好生产,我希望其他人不要 运行我花了很多时间用 Phantom 构建后遇到的问题。
我目前正在考虑在 PlayFramework 项目中使用 Cassandra 作为我的数据库。我一直在寻找反应式驱动程序,但我的选择似乎仅限于 Phantom 和 Quill。 我在 nosql 数据库方面的经验仅限于 MongoDB,而且我之前没有使用过任何 Quill 或 Phantom。
看看 comparison here ,似乎最终可能会在 Phantom 中编写更多代码。此外,使用 DSL 来描述模型似乎违反直觉(来自沉重的 hibernate/JPA 背景)——但这可能就是我。
我想知道是否有人可以提供实用的 advice/use 案例,其中一个案例 excel 和每个案例中需要注意的事项?
作为phantom的作者,我对phantom的设计目标把握得非常好。 Quill库网站上已有Quill和Phantom的对比,自然是偏向另一个方向。
Phantom 旨在成为应用程序层的完美选择,而 Quill 旨在成为最出色的字符串生成器,当您在 Cassandra 之上构建大型应用程序时,这不是一个非常有用的比较。
使用 phantom 的优点
关于类型安全以及 DSL 对 Cassandra 功能的改进程度,确实没有争议。 DSL 非常 "intimate" 了解您的数据结构,并提供对 Cassandra 功能的完整支持。它在编译时知道关于 Cassandra 什么是可能的,什么不是。
Quill 开发者认为 phantom 有更多的依赖关系,但这并不完全准确,因为其中大部分是可选的,包括 Play iteratees 和流支持等。得不到你想要的,就这么简单。
Quill 比较简单地指出:"You could extend Phantom by extending the DSL to add new features, although it might not be a straightforward process.",这有点不准确。作为游戏中的新玩家,Quill 在 Cassandra 功能支持方面是一个玩具,您会经常发现自己需要添加功能。 Phantom 无疑有其不足之处,但它是一个成熟得多的替代方案,并且需要扩展的次数要少得多。
对于更复杂的功能,我们已经在数天或数周内解决了大多数错误,但通常您可能需要的一切都已经存在,其中一些功能目前在 Quill 中找不到,这需要我小时连写下来。
我没有很强的 JPA 背景,但是 Cassandra 和 phantom 之间的映射是一个非常强大的层,因为它允许你自动生成 tables 直接来自映射 DSL。它还允许 DSL 在编译时完全模仿 Cassandra 的行为,它会知道关于您选择的主键等哪些查询是可能的,quill 根本没有这样的支持。
Phantom 具有非常强大的应用程序级抽象层,例如连接器、数据库、自动生成数据库,可以帮助您 运行 将应用程序投入生产。
Quill 背后的代码要复杂得多,虽然我会第一个高度赞扬它背后的工程能力,但当我认为用户友好时,这个故事就不太成立了还有。
Quill 尝试一次性完成更多工作。这是一个用于生成的迷你引擎,几年前 scalaquery 在决定完全专注于 SQL dbs 并放弃对其他任何东西的支持之前试图做的事情。它是现代 Slick 的前身,并使用类似的 QDSL 引用方法。
Quill 是一个泄漏的抽象。由于他们旨在支持更广泛的数据库,因此他们对数据库细节的特殊性的支持要差得多。示例如下:
从比较中最基本的例子中你读到:
val getAllByCountry = quote {
(country: String) => query[WeatherStation]
.filter(_.country == country)
}
}
到目前为止一切都很好,如果我们包含必要的映射代码,大概比虚幻的等价物更简洁。
select.where(_.country eqs country).fetch()
但让我们进一步探索。如果你想像这样获取一个国家怎么办?或者,如果您尝试获取 PagingState
信息怎么办?或者输入现有 PagingState
以在 UI.
这就是 Quill 至少在比较中未能让用户真正预览他们最终体验的地方。很自然地假设,无论何时您转到某个工具的页面,它都会将自己描述为同类中最好的工具,就像我们 phantom 背后的人所做的那样,但这绝不是全部故事。
为了更简洁,更酷的东西:
select.where(_.country eqs country).fetchRecord()
select.where(_.country eqs country).one()
部分 select 怎么样?
select(_.country, _.city).where(_.country eqs country)
Phantom 在使用 Cassandra 运行 时在语义上区分所有可能的事情,它首先尝试使用编译时技巧和领域知识来防止 运行 时间错误。你怎么能有 Quill 等价物?
此外,Quill 完全能够直接从 case class
.
case class WeatherStation(
country: String,
city: String,
stationId: String,
entry: Int,
value: Int
)
object WeatherStation {
val getAllByCountry = quote {
(country: String) =>
query[WeatherStation].filter(_.country == country)
}
val getAllByCountryAndCity = quote {
(country: String, city: String) =>
getAllByCountry(country).filter(_.city == city)
}
val getAllByCountryCityAndId = quote {
(country: String, city: String, stationId: String) =>
getAllByCountryAndCity(country, city).filter(_.stationId == stationId)
}
}
但它缺乏关于您的架构的任何知识。如果国家不是主要国家的一部分怎么办?该查询无效,phantom 不会让你编译它,这只是最基本的例子。
Phantom 可以直接从 table 自动生成你的 CQL,它可以即时生成整个数据库,专业版甚至可以自动迁移 tables 并帮助你处理模式不一致,并为您提供非常先进的 UI 和监控界面,您可以在其中动态升级和降级模式。
缺点
Phantom 确实使
TypeCodec
之类的扩展变得稍微不那么冗长,但是从 phantom 2.9.0 开始,我们引入了一个非常强大的宏机制来编码 Cassandra 中的类型完全不依赖TypeCodec
!Phantom 在定义 table DSL 时需要最少的样板文件,并且本质上不能很好地共享 table 列。可以做到,但不是最美的代码,也不是最差的。
总体
- Quill 是一个非常好的软件,由非常有才华的人编写,对此毫无疑问。
- 严格来说,它比 phantom 在查询生成方面要好,有样板可以通过 QDSL 减少,而不能通过 EDSL 减少,如果我们打架谁是最精简的字符串生成器 Quill 获胜。
- 它在应用层是一个非常差的工具,对大多数人来说更不自然。 Slick 在某种程度上普及了这些概念,但是您想要作为应用程序生命周期一部分的一些最基本的功能并不能通过 QDSL 轻松解决,或者至少它还没有实现。
- Phantom 更加成熟,并且被广泛采用,拥有更多的资源和来自创始团队的投入、长期的路线图以及与 Datastax 的重要合作伙伴关系,这有助于我们掌握所有功能。
我们从 Quill 开始,然后由于 Phantom 的功能和易于更改而转向 Phantom。然而,我们 运行 在负载测试中遇到了严重的问题,发现它没有释放 CPU 线程和网络连接。我们在本地 mac machine 以及 AMI Linux 服务器的 AWS EC2 集群上进行了测试。本质上资源没有被释放,内存不足的异常将随之而来。如果这个问题得到解决,Phantom 就很棒了。就目前而言,我不能向任何拥有需要高性能的生产系统的人推荐使用 Phantom。
在生产的最后一刻,我们不得不更改所有代码并切换回 Quill,这让我很痛苦。
我已经用 Phantom 提出了一个问题,希望他们能尽快解决这个问题。随附的是一个项目,通过 运行 并排运行一个简单的 JSON/REST scala 项目来测试 Quill 和 Phantom 之间的负载。
https://github.com/yleun/cassandra-loadtest
如果 Phantom 可以解决这个内存不足的异常,它可能是一个优于 Quill 的数据库客户端,但就目前而言,它还没有准备好生产,我希望其他人不要 运行我花了很多时间用 Phantom 构建后遇到的问题。