Cassandra - 用于查询整个分区的 IN 或 TOKEN 查询?
Cassandra - IN or TOKEN query for querying an entire partition?
我想查询我的 table 的完整分区。
我的复合分区键由 (id, date, hour_of_timestamp)
组成。 id
和 date
是字符串,hour_of_timestamp
是整数。
由于摄取数据时存在热点,我需要将 hour_of_timestamp 字段添加到我的分区键。
现在我想知道查询完整数据分区的最有效方法是什么?
根据 this blog,使用 SELECT * from mytable WHERE id = 'x' AND date = '10-10-2016' AND hour_of_timestamp IN (0,1,...23);
会在协调器节点上造成大量开销。
是不是用TOKEN函数查询两个token的分区比较好?比如SELECT * from mytable WHERE TOKEN(id,date,hour_of_timestamp) >= TOKEN('x','10-10-2016',0) AND TOKEN(id,date,hour_of_timestamp) <= TOKEN('x','10-10-2016',23);
所以我的问题是:
我应该使用 IN
还是 TOKEN
查询来查询我的数据的整个分区?或者我应该使用 23 个查询(hour_of_timestamp
的每个值一个)并让驱动程序完成其余的?
我正在使用 Cassandra 3.0.8 和最新的 Datastax Java 驱动程序连接到 6 节点集群。
你说:
Now I'm wondering what's the most efficient way to query a complete
partition of my data? According to this blog, using SELECT * from
mytable WHERE id = 'x' AND date = '10-10-2016' AND hour_of_timestamp
IN (0,1,...23); is causing a lot of overhead on the coordinator node.
但实际上您会查询 24 个分区。
您的意思可能是您有一个设计,其中单个分区现在由 24 个分区组成,因为您添加了小时以避免数据摄取期间的热点。请注意,在两种模型(带有热点的旧模型和这个新模型)中,数据都是 still 按时间戳排序,您有两个选择:
- 运行 1 个查询。
- 运行 第一次查询 2 个,然后一次查询 "prefetch" 个结果。
- 运行 24 个并行查询。
案例 1
如果按顺序处理数据,首选是 运行 小时 0 的查询,处理数据,完成后,运行 小时 1 的查询,依此类推...这是一个简单的实现,我认为它不值得比这更多。
案例 2
如果您的查询比数据处理花费的时间更多,您可以 "prefetch" 一些数据。所以,第一次可以运行2个并行查询得到0小时和1小时的数据,然后开始处理0小时的数据。与此同时,1小时的数据到了,所以当你完成要处理第 0 小时的数据,您可以预取第 2 小时的数据并开始处理第 1 小时的数据。依此类推......这样您可以加快数据处理速度。当然,根据您的时间安排(数据处理和查询时间),您应该优化 "prefetch" 查询的数量。
另请注意,Java 驱动程序会自动为您分页,并且根据检索分区的大小,您可能希望禁用该功能以避免阻塞数据处理,或者可能希望获取使用 this:
之类的东西抢占更多数据
ResultSet rs = session.execute("your query");
for (Row row : rs) {
if (rs.getAvailableWithoutFetching() == 100 && !rs.isFullyFetched())
rs.fetchMoreResults(); // this is asynchronous
// Process the row ...
}
您可以在哪里调整 rs.getAvailableWithoutFetching() == 100
以更好地满足您的预取要求。
您可能还希望第一次预取多个分区,以确保您的处理不会等待任何数据获取部分。
案例 3
如果您需要一起处理来自不同分区的数据,例如您需要第 3 小时和第 6 小时的数据,那么您可以尝试按 "dependency" 对数据进行分组(例如并行查询第 3 小时和第 6 小时).
如果你需要所有这些,那么应该 运行 并行查询 24,然后在应用程序级别加入它们(你已经知道为什么你应该避免多个分区的 IN)。请记住,您的数据已 已经 订购,因此您的应用程序级工作将非常小。
我想查询我的 table 的完整分区。
我的复合分区键由 (id, date, hour_of_timestamp)
组成。 id
和 date
是字符串,hour_of_timestamp
是整数。
由于摄取数据时存在热点,我需要将 hour_of_timestamp 字段添加到我的分区键。
现在我想知道查询完整数据分区的最有效方法是什么?
根据 this blog,使用 SELECT * from mytable WHERE id = 'x' AND date = '10-10-2016' AND hour_of_timestamp IN (0,1,...23);
会在协调器节点上造成大量开销。
是不是用TOKEN函数查询两个token的分区比较好?比如SELECT * from mytable WHERE TOKEN(id,date,hour_of_timestamp) >= TOKEN('x','10-10-2016',0) AND TOKEN(id,date,hour_of_timestamp) <= TOKEN('x','10-10-2016',23);
所以我的问题是:
我应该使用 IN
还是 TOKEN
查询来查询我的数据的整个分区?或者我应该使用 23 个查询(hour_of_timestamp
的每个值一个)并让驱动程序完成其余的?
我正在使用 Cassandra 3.0.8 和最新的 Datastax Java 驱动程序连接到 6 节点集群。
你说:
Now I'm wondering what's the most efficient way to query a complete partition of my data? According to this blog, using SELECT * from mytable WHERE id = 'x' AND date = '10-10-2016' AND hour_of_timestamp IN (0,1,...23); is causing a lot of overhead on the coordinator node.
但实际上您会查询 24 个分区。
您的意思可能是您有一个设计,其中单个分区现在由 24 个分区组成,因为您添加了小时以避免数据摄取期间的热点。请注意,在两种模型(带有热点的旧模型和这个新模型)中,数据都是 still 按时间戳排序,您有两个选择:
- 运行 1 个查询。
- 运行 第一次查询 2 个,然后一次查询 "prefetch" 个结果。
- 运行 24 个并行查询。
案例 1
如果按顺序处理数据,首选是 运行 小时 0 的查询,处理数据,完成后,运行 小时 1 的查询,依此类推...这是一个简单的实现,我认为它不值得比这更多。
案例 2
如果您的查询比数据处理花费的时间更多,您可以 "prefetch" 一些数据。所以,第一次可以运行2个并行查询得到0小时和1小时的数据,然后开始处理0小时的数据。与此同时,1小时的数据到了,所以当你完成要处理第 0 小时的数据,您可以预取第 2 小时的数据并开始处理第 1 小时的数据。依此类推......这样您可以加快数据处理速度。当然,根据您的时间安排(数据处理和查询时间),您应该优化 "prefetch" 查询的数量。
另请注意,Java 驱动程序会自动为您分页,并且根据检索分区的大小,您可能希望禁用该功能以避免阻塞数据处理,或者可能希望获取使用 this:
之类的东西抢占更多数据ResultSet rs = session.execute("your query");
for (Row row : rs) {
if (rs.getAvailableWithoutFetching() == 100 && !rs.isFullyFetched())
rs.fetchMoreResults(); // this is asynchronous
// Process the row ...
}
您可以在哪里调整 rs.getAvailableWithoutFetching() == 100
以更好地满足您的预取要求。
您可能还希望第一次预取多个分区,以确保您的处理不会等待任何数据获取部分。
案例 3
如果您需要一起处理来自不同分区的数据,例如您需要第 3 小时和第 6 小时的数据,那么您可以尝试按 "dependency" 对数据进行分组(例如并行查询第 3 小时和第 6 小时).
如果你需要所有这些,那么应该 运行 并行查询 24,然后在应用程序级别加入它们(你已经知道为什么你应该避免多个分区的 IN)。请记住,您的数据已 已经 订购,因此您的应用程序级工作将非常小。