Google BigQuery查询速度很慢

时间:2014-10-16 08:53:04

标签: php sql google-app-engine bigdata google-bigquery

我正在使用Google BigQuery,我正在从PHP执行一些简单的查询。 (例如SELECT *来自电子邮件WHERE email =' mail@test.com')我只是检查表格中是否存在电子邮件。

表格"电子邮件"现在是空的。但是PHP脚本还需要大约4分钟才能检查空表上的175封电子邮件。正如我希望将来表格将被填充并且将有50万封邮件然后我想请求时间会更长。

这是正常的吗?或者是否有任何改进检查时间的想法/解决方案?

(P.S。:表"电子邮件"只包含8列,都是字符串类型)

谢谢!

2 个答案:

答案 0 :(得分:3)

如果您只是检查是否存在字段,请考虑使用SELECT COUNT(*) FROM emails where email='mail@test.com'。这只需要读取一个字段,因此在大型表格上花费更少,速度更快。

正如Pentium10建议的那样,考虑在单个查询中使用多个查找。你可以这样做:

SELECT SUM((IF(email = 'mail1@test.com', 1, 0)) as m1,
       SUM((IF(email = 'mail2@test.com', 1, 0)) as m2,
       SUM((IF(email = 'mail3@test.com', 1, 0)) as m3,
       ...
 FROM emails

在单个查询中,您将被限制为64k这样的内容,但计算速度非常快,因为它只需要在一次扫描中扫描单个列。

或者,如果您希望每行发送一封电子邮件,您可以做一些像

这样的爱好者。
 SELECT email FROM emails WHERE email IN
 ('mail1@test.com', 'mail2@test.com', 'mail3@test.com'...)
 GROUP BY email

作为进一步优化,您可以将其作为LEFT JOIN:

SELECT t1.email as email, IF(t2.email is not null, true, false) as found 
FROM [interesting_emails] t1  
LEFT OUTER JOIN [emails] t2 ON t1.email = t2.email

如果interesting_emails有您要检查的电子邮件列表,例如

mail1@test.com
mail2@test.com
mail3@test.com

如果电子邮件表只包含mail1 @和maiil2 @,那么您将获得结果:

email            found
______________   _____
mail1@test.com   true
mail2@test.com   false
mail3@test.com   true

这样做的好处是,如果需要,它可以扩展到数十亿封电子邮件(当数量变大时,你可以考虑使用JOIN EACH而不是JOIN)。

答案 1 :(得分:1)

以下是PHP中使用官方https://github.com/google/google-api-php-client

进行流媒体插入的示例代码
/**
 * 
 * @param type $client
 * @param type $project_id
 * @param type $dataset_id
 * @param type $rows
 * @return boolean
 * @throws Google_Service_Exception
 */
public function BQ_Tabledata_InsertAll($client, $project_id, $dataset_id, $rows) {
    $bq = new Google_Service_Bigquery($client);
    $request = new Google_Service_Bigquery_TableDataInsertAllRequest();
    $request->setRows($rows);
    try {
        $resp = new Google_Service_Bigquery_TableDataInsertAllResponse();
        $resp = $bq->tabledata->insertAll($project_id, $dataset_id, static::tableId(), $request);
        $errors = new Google_Service_Bigquery_TableDataInsertAllResponseInsertErrors();
        $errors = @$resp->getInsertErrors();
        if (!empty($errors)) {
            $error_msg = '';
            if (is_array($errors)) {
                $line = 0;
                foreach ($errors as $eP) {
                    $arr = $eP->getErrors();
                    if (is_array($arr)) {
                        foreach ($arr as $e) {
                            switch ($e->getReason()) {
                                case "stopped":
                                    break;
                                default:
                                    $error_msg.= sprintf("Error on line %s: %s\r\n", $line, $e->getMessage());
                                    break;
                            }
                        }
                    }
                    $line++;
                }
                $this->setErrorMessage($error_msg);
            } else {
                $this->setErrorMessage($errors);
            }
            //print_r($errors);
            //exit;
            return false;
        }
        return true;
    } catch (Google_Service_Exception $e) {
        $this->setErrors($e->getErrors())->setErrorMessage($e->getMessage());
        throw $e;
    }
}