当我们使用 Limit 时是否有任何性能优势
Is there any performance benefit when we use Limit
例如
SELECT company_ID, totalRevenue
FROM `BigQuery.BQdataset.companyperformance`
ORDER BY totalRevenue LIMIT 10
我能看到使用和不使用 LIMIT 10 之间的唯一区别只是用于向用户显示的数据量不同。
在执行 LIMIT 之前,系统仍然会先对所有数据进行排序。
此答案假定您询问的是以下两个变体之间的区别:
ORDER BY totalRevenue
ORDER BY totalRevenue LIMIT 10
在许多数据库中,如果存在涉及 totalRevenue
的 suitable 索引,LIMIT
查询可能会在找到前 10 条记录后停止排序。
正如您所指出的,在没有任何索引的情况下,两个版本都必须进行完整排序,因此应该执行相同的操作。
此外,如果 table 很大,则两者之间可能存在重大性能差异。在 LIMIT
版本中,BigQuery 只需发送 10 条记录,而在非 LIMIT
版本中,可能需要发送更多数据。
没有性能提升。 bigQuery 仍然遍历了 table.
上的所有记录
您可以对数据进行分区,以减少 bigQuery 必须读取的记录量。这将提高性能。您可以在此处阅读更多信息:
https://cloud.google.com/bigquery/docs/partitioned-tables
在 bigQuery UI 中查看以下 2 个查询之间的统计差异
SELECT * FROM `bigquery-public-data.hacker_news.comments` LIMIT 1000
SELECT * FROM `bigquery-public-data.hacker_news.comments` LIMIT 10000
如您所见,在达到限制标准后,BQ 会立即 return 到 UI,这会带来更好的性能和更少的网络流量
以下适用于 BigQuery
在技术上不一定 100% 正确 - 但足够接近,所以我希望下面能让您了解为什么 LIMIT N 在 BigQuery 中非常重要
假设您有 1,000,000 行数据和 8 个工作人员来处理如下查询
SELECT * FROM table_with_1000000_rows ORDER BY some_field
第 1 轮:为了对这些数据进行排序,每个工作人员获得 125,000 行 – 所以现在您有 8 个排序集,每个集有 125,000 行
第 2 轮:Worker #1 将其排序后的数据(125,000 行)发送给 worker #2,#3 发送给 #4,依此类推。所以现在我们有 4 个工人,每个工人生产 250,000 行的有序集
第 3 轮:重复上述逻辑,现在我们只有 2 个工作人员,每个工作人员生成 500,000 行的有序列表
第 4 轮:最后,只有一名工人生产出 1,000,000 行的最终有序集
当然,根据行数和可用工人数——轮数可能与上述示例不同
总结:我们这里有:
一种。我们有大量的数据在工作人员之间传输——这可能是性能下降的一个重要因素
b.我们有机会让其中一名工作人员无法处理分配给相应工作人员的数据量。它可能发生得更早或更晚,通常表现为“资源超出……”类型的错误
所以,现在如果您将 LIMIT 作为查询的一部分,如下所示
SELECT * FROM table_with_1000000_rows ORDER BY some_field LIMIT 10
所以,现在 - 第一轮将是一样的。但是从第 2 轮开始——只有前 10 行将被发送给另一个工人——因此在第一轮之后的每一轮中——只有 20 行将被处理,并且只有前 10 行将被发送以进行进一步处理
希望您看到这两个进程在工作人员之间发送的数据量方面有何不同,以及每个工作人员需要应用多少工作来对各自的数据进行排序
总结:
没有限制 10:
• 最初移动的行数(第 1 轮):1,000,000;
• 最初订购的行数(第 1 轮):1,000,000;
• 移动中间行(第 2 - 4 轮):1,500,000
• 总体合并有序行(第 2 - 4 轮):1,500,000;
• 最终结果:1,000,000 行
限制为 10:
• 最初移动的行数(第 1 轮):1,000,000;
• 最初订购的行数(第 1 轮):1,000,000;
• 移动中间行(第 2 - 4 轮):70
• 总体合并有序行(第 2 - 4 轮):140;
• 最终结果:10 行
希望以上数字清楚地表明您使用 LIMIT N 获得的性能差异,并且在某些情况下甚至能够成功 运行 查询而没有 "Resource exceeded ..." 错误
例如
SELECT company_ID, totalRevenue
FROM `BigQuery.BQdataset.companyperformance`
ORDER BY totalRevenue LIMIT 10
我能看到使用和不使用 LIMIT 10 之间的唯一区别只是用于向用户显示的数据量不同。 在执行 LIMIT 之前,系统仍然会先对所有数据进行排序。
此答案假定您询问的是以下两个变体之间的区别:
ORDER BY totalRevenue
ORDER BY totalRevenue LIMIT 10
在许多数据库中,如果存在涉及 totalRevenue
的 suitable 索引,LIMIT
查询可能会在找到前 10 条记录后停止排序。
正如您所指出的,在没有任何索引的情况下,两个版本都必须进行完整排序,因此应该执行相同的操作。
此外,如果 table 很大,则两者之间可能存在重大性能差异。在 LIMIT
版本中,BigQuery 只需发送 10 条记录,而在非 LIMIT
版本中,可能需要发送更多数据。
没有性能提升。 bigQuery 仍然遍历了 table.
上的所有记录您可以对数据进行分区,以减少 bigQuery 必须读取的记录量。这将提高性能。您可以在此处阅读更多信息: https://cloud.google.com/bigquery/docs/partitioned-tables
在 bigQuery UI 中查看以下 2 个查询之间的统计差异
SELECT * FROM `bigquery-public-data.hacker_news.comments` LIMIT 1000
SELECT * FROM `bigquery-public-data.hacker_news.comments` LIMIT 10000
如您所见,在达到限制标准后,BQ 会立即 return 到 UI,这会带来更好的性能和更少的网络流量
以下适用于 BigQuery
在技术上不一定 100% 正确 - 但足够接近,所以我希望下面能让您了解为什么 LIMIT N 在 BigQuery 中非常重要
假设您有 1,000,000 行数据和 8 个工作人员来处理如下查询
SELECT * FROM table_with_1000000_rows ORDER BY some_field
第 1 轮:为了对这些数据进行排序,每个工作人员获得 125,000 行 – 所以现在您有 8 个排序集,每个集有 125,000 行
第 2 轮:Worker #1 将其排序后的数据(125,000 行)发送给 worker #2,#3 发送给 #4,依此类推。所以现在我们有 4 个工人,每个工人生产 250,000 行的有序集
第 3 轮:重复上述逻辑,现在我们只有 2 个工作人员,每个工作人员生成 500,000 行的有序列表
第 4 轮:最后,只有一名工人生产出 1,000,000 行的最终有序集
当然,根据行数和可用工人数——轮数可能与上述示例不同
总结:我们这里有:
一种。我们有大量的数据在工作人员之间传输——这可能是性能下降的一个重要因素
b.我们有机会让其中一名工作人员无法处理分配给相应工作人员的数据量。它可能发生得更早或更晚,通常表现为“资源超出……”类型的错误
所以,现在如果您将 LIMIT 作为查询的一部分,如下所示
SELECT * FROM table_with_1000000_rows ORDER BY some_field LIMIT 10
所以,现在 - 第一轮将是一样的。但是从第 2 轮开始——只有前 10 行将被发送给另一个工人——因此在第一轮之后的每一轮中——只有 20 行将被处理,并且只有前 10 行将被发送以进行进一步处理 希望您看到这两个进程在工作人员之间发送的数据量方面有何不同,以及每个工作人员需要应用多少工作来对各自的数据进行排序
总结:
没有限制 10:
• 最初移动的行数(第 1 轮):1,000,000;
• 最初订购的行数(第 1 轮):1,000,000;
• 移动中间行(第 2 - 4 轮):1,500,000
• 总体合并有序行(第 2 - 4 轮):1,500,000;
• 最终结果:1,000,000 行
限制为 10:
• 最初移动的行数(第 1 轮):1,000,000;
• 最初订购的行数(第 1 轮):1,000,000;
• 移动中间行(第 2 - 4 轮):70
• 总体合并有序行(第 2 - 4 轮):140;
• 最终结果:10 行
希望以上数字清楚地表明您使用 LIMIT N 获得的性能差异,并且在某些情况下甚至能够成功 运行 查询而没有 "Resource exceeded ..." 错误