错误是因为limit size for a variable is 1MB。
关于处理批次的循环。您可以使用以下 SQL 作为参考:
DECLARE offset_ INT64 DEFAULT 1; -- OFFSET starts in 1 BASED on ROW NUMBER ()
DECLARE limit_ INT64 DEFAULT 500; -- Size of the chunks to be processed
DECLARE size_ INT64 DEFAULT 7000; -- Size of the data (used for the condition in the WHILE loop)
-- Table to be processed. I'm creating this new temporary table to use it as an example
CREATE TEMPORARY TABLE IF NOT EXISTS data_numbered AS (
SELECT *, ROW_NUMBER() OVER() row_number
FROM (SELECT * FROM `bigquery-public-data.stackoverflow.users` LIMIT 7000)
);
-- WHILE loop
WHILE offset_ < size_ DO
IF offset_ = 1 THEN -- OPTIONAL, create the temporary table in the first iteration
CREATE OR REPLACE TEMPORARY TABLE temp_table AS (
SELECT * FROM data_numbered
WHERE row_number BETWEEN offset_ AND offset_ + limit_ - 1 -- Use offset and limit to control the chunks of data
);
ELSE
-- This is the same query as above.
-- Each iteration will fill the temporary table
-- Iteration
-- 501 - 1000
-- 1001 - 1500
-- ...
INSERT INTO temp_table (
SELECT * FROM data_numbered WHERE row_number BETWEEN offset_ AND offset_ + limit_ - 1 -- -1 because BETWEEN is inclusive, so it helps to avoid duplicated values in the edges
);
END IF;
-- Adjust the offset_ variable
SET offset_ = offset_ + limit_;
END WHILE;
制作此循环的挑战之一是您不能在 LIMIT 和 OFFSET 子句中使用变量。因此,我使用 ROW_NUMBER() 创建了一个列,我可以用它来处理 WHERE 子句:
WHERE row_number BETWEEN offset_ AND offset_ + limit_
如果您想了解更多关于 ROW_NUMBER() 的信息,我建议您查看this SO answer。
最后,如果您想使用这种方法,请考虑一些注意事项,例如脚本是Beta feature,并且可能是quota issues,具体取决于您将数据插入临时表的频率。另外,由于查询在每次迭代中都会发生变化,第一次运行时,它没有缓存,bytes_processed 将是表的 number_of_iterations*byte_size