from smallpond.common import GB from smallpond.execution.driver import Driver from smallpond.logical.dataset import ParquetDataSet from smallpond.logical.node import ( Context, DataSetPartitionNode, DataSourceNode, HashPartitionNode, LogicalPlan, SqlEngineNode, ) def shuffle_mock_urls( input_paths, npartitions: int = 10, sort_rand_keys=True, engine_type="duckdb" ) -> LogicalPlan: ctx = Context() dataset = ParquetDataSet(input_paths) data_files = DataSourceNode(ctx, dataset) data_partitions = DataSetPartitionNode(ctx, (data_files,), npartitions=npartitions) urls_partitions = HashPartitionNode( ctx, (data_partitions,), npartitions=npartitions, hash_columns=None, random_shuffle=True, engine_type=engine_type, output_name="urls_partitions", cpu_limit=1, memory_limit=20 * GB, ) if sort_rand_keys: # shuffle as sorting partition keys shuffled_urls = SqlEngineNode( ctx, (urls_partitions,), r"select *, random() as partition_key from {0} order by partition_key", output_name="shuffled_urls", cpu_limit=1, memory_limit=40 * GB, ) else: # shuffle as reservoir sampling shuffled_urls = SqlEngineNode( ctx, (urls_partitions,), r"select * from {0} using sample 100% (reservoir, {rand_seed})", output_name="shuffled_urls", cpu_limit=1, memory_limit=40 * GB, ) plan = LogicalPlan(ctx, shuffled_urls) return plan def main(): driver = Driver() driver.add_argument("-i", "--input_paths", nargs="+") driver.add_argument("-n", "--npartitions", type=int, default=500) driver.add_argument("-s", "--sort_rand_keys", action="store_true") driver.add_argument( "-e", "--engine_type", default="duckdb", choices=("duckdb", "arrow") ) plan = shuffle_mock_urls(**driver.get_arguments()) driver.run(plan) if __name__ == "__main__": main()