🐖

BigQueryで長いSQLを流したいよぅ(BQリソースオーバー)

2023/06/01に公開

エラー文はたしか

Query too large error: Your query exceeded the maximum allowed size.

だと思います。これはおそらくcsvとかjsonでinsertすればいいと思います。
updateは?

そもそもupdateとかは推奨されてないらしいです。消していれなおせと。そういうことらしい。
でも長文insert,updateSQLを流したい!いや流せないんで分割するしかないです。

その場合のphpサンプルになります。なのでBQのテクニックみたいのじゃないです。

PHPサンプル

insertの例になります。1文ずつだと、時間も金もかかるので大きく5分割くらいにしよう!

$add_values = array("0" => "", "1" => "", "2" => "", "3" => "", "4" => "");
$no=1;
foreach ($date as $record) {
	$which = $no%4;
	$no++;

	if(!$add_values[$which])
		$add_values[$which] .= "values(";
	else
		$add_values[$which] .= ",(";

	$add_values[$which] .= '1, 2, 3, 4, 5';
	$add_values[$which] .= ")";
}

//これを5個書くかループさせる
if($add_values["1"]) {
	$query = "insert into `bq.bbq.barbecue`(one, two, three, four, five)".$add_values["1"];
	$jobConfig = $bigQuery->query($query);
	$queryResults = $bigQuery->runQuery($jobConfig);
}

こう書くと、

insert into `bq.bbq.barbecue`(`one`, `two`, `three`, `four`, `five`)
values(1, 2, 3, 4, 5)
,(6, 7, 8, 9, 10)

みたいに連結された長いSQLが5つできるかもしれない感じです。

ほなupdateは?

「注意点として、BigQueryの更新操作は比較的高コストな操作」をGPTさんも言っています。
updateの方が癖があります。SQLが、ですけど。2つ項目をアップデートするパターンを例に示します。

update `bq.bbq.barbecue` set
	`one` = CASE (`two`, `three`)
		WHEN (2, 3) THEN 10
		WHEN (7, 8) THEN 20
	END,
	`four` = CASE (`two`, `three`)
		WHEN (2, 3) THEN 30
		WHEN (7, 8) THEN 40
where (`two`, `three`) in (
	(2, 3), (7, 8)
)

この例は一意なIDがない感じのやつです。なので複雑ですね。
がこれで、
two, threeが2, 3の場合、oneに10が入り、
two, threeが7, 8の場合、oneに20が入ります。

where句の条件は「where true」でいい気もしますが、別の条件が必要な場合はそれをいれます。

//今回は偶数奇数
$add_when_one = array("odd" => "", "even" => "");
$add_when_four = array("odd" => "", "even" => "");

//2カラムで偶数奇数分なので、2つずついります。
$query = "update `bq.bbq.barbecue` set";
	$add_when_one["odd"] = " one = CASE (`two`, `three`)";
	$add_when_one["even"] = " one = CASE (`two`, `three`)";
	$add_when_four["odd"] = ",four = CASE (`two`, `three`)";
	$add_when_four["even"] = ",four = CASE (`two`, `three`)";
$add_where["odd"] = "";
$add_where["even"] = "";

$no=1;
foreach($data as $record){
	if ($no % 2 == 0)
		$which = "even";
	else
		$which = "odd";

	$no++;

	$add_when_one[$which] .= " WHEN (2, 3) THEN 10";
	$add_when_four[$which] .= " WHEN (2, 3) THEN 30";
	if(!$add_where[$which])
		$add_where[$which] .= " where (`two`, `three`) in( (";
	else
		$add_where[$which] .= ",(";

	$add_where[$which] .= "2, 3)";
}

$add_when_one["odd"] .= " END";
$add_when_one["even"] .= " END";
$add_when_four["odd"] .= " END";
$add_when_four["even"] .= " END";
$add_where["odd"] .= " )";
$add_where["even"] .= " )";

//SQLを確認してみてくださいね
var_dump($query.$add_when_one["odd"].$add_when_four["odd"].$add_where["odd"]);
var_dump($query.$add_when_one["even"].$add_when_four["even"].$add_where["even"]);
exit();

$jobConfig = $bigQuery->query($query.$add_when_one["odd"].$add_when_four["odd"].$add_where["odd"]);
$queryResults = $bigQuery->runQuery($jobConfig);

$jobConfig = $bigQuery->query($query.$add_when_one["even"].$add_when_four["even"].$add_where["even"]);
$queryResults = $bigQuery->runQuery($jobConfig);

マヂ混乱ですね。

Discussion