改进BigQuery不区分大小写的搜索性能

Fel*_*ffa 5 performance google-bigquery

BigQuery团队再次罢工:这个问题不再相关,因为LOWER()的结果与REGEX()现在一样快.


使用BigQuery处理~5GB的数据应该超级快.例如,以下查询在18秒内执行不区分大小写的搜索:

#standardSQL
SELECT COUNT(*) c
FROM `bigquery-public-data.hacker_news.full` 
WHERE 
  LOWER(text) LIKE '%bigquery%' # 18s
Run Code Online (Sandbox Code Playgroud)

通常BigQuery比这更快,但真正的问题是添加新的搜索词会使这个查询相当慢(几乎一分钟有3个搜索词):

#standardSQL
SELECT COUNT(*) c
FROM `bigquery-public-data.hacker_news.full` 
WHERE 
  LOWER(text) LIKE '%bigquery%' OR LOWER(text) LIKE '%big query%' # 34s

#standardSQL
SELECT COUNT(*) c
FROM `bigquery-public-data.hacker_news.full` 
WHERE 
  LOWER(text) LIKE '%bigquery%' OR LOWER(text) LIKE '%big query%'
  OR LOWER(text) LIKE '%google cloud%' # 52s
Run Code Online (Sandbox Code Playgroud)

如何提高查询性能?

Fel*_*ffa 10

团队提示:敬请关注!很快BigQuery就会把这个建议变得无关紧要.

BigQuery性能提示:避免使用LOWER()UPPER()

LOWER()UPPER()操作使用Unicode文本打交道时,有一个困难时期:每个字符需要单独映射,它们也可以是多字节.

解决方案1:不区分大小写的正则表达式

更快的替代方法:使用REGEX_MATCH()并将不区分大小写的(?i)修饰符添加到正则表达式中

#standardSQL
SELECT COUNT(*) c
FROM `bigquery-public-data.hacker_news.full` 
WHERE 
   REGEXP_CONTAINS(text, '(?i)bigquery') # 7s

#  REGEXP_CONTAINS(text, '(?i)bigquery')
#   OR REGEXP_CONTAINS(text, '(?i)big query') # 9s

#  REGEXP_CONTAINS(text, '(?i)bigquery') 
#   OR REGEXP_CONTAINS(text, '(?i)big query') 
#   OR REGEXP_CONTAINS(text, '(?i)google cloud') # 11s
Run Code Online (Sandbox Code Playgroud)

这种方式的性能要好得多:

  • 1搜索词:18s到8s
  • 2个搜索词:34s到9s
  • 3个搜索词:52s到11s.

解决方案2:结合正则表达式

为什么正则表达式可以将多个组合成1时进行3次搜索?

#standardSQL
SELECT COUNT(*) c
FROM `bigquery-public-data.hacker_news.full` 
WHERE 
  REGEXP_CONTAINS(text, '(?i)(bigquery|big query|google cloud)') # 7s
Run Code Online (Sandbox Code Playgroud)

7s中的3个术语 - 很好.

解决方案3:转换为字节

这是更加丑陋的,但在处理单个字节时显示UPPER()LOWER()执行得更好 - 在这些搜索中获得相同的结果:

#standardSQL
SELECT COUNT(*) c
FROM `bigquery-public-data.hacker_news.full` 
WHERE 
  LOWER(CAST(text AS BYTES)) LIKE b'%bigquery%'
  OR LOWER(CAST(text AS BYTES)) LIKE b'%big query%' 
  OR LOWER(CAST(text AS BYTES)) LIKE b'%google cloud%' # 7s
Run Code Online (Sandbox Code Playgroud)

LOWER()速度较慢.请改用正则表达式(?i)修饰符.

如果这对您有用,请随时评论您的性能改进.