提高 BigQuery 不区分大小写的搜索性能

Posted

技术标签:

【中文标题】提高 BigQuery 不区分大小写的搜索性能【英文标题】:Improve BigQuery case insensitive search performance 【发布时间】:2018-01-24 07:13:30 【问题描述】:

BigQuery 团队再次出击:这个问题不再相关,因为现在使用 LOWER() 的结果与使用 REGEX() 的结果一样快。


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

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

通常 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

如何提高查询性能?

【问题讨论】:

【参考方案1】:

团队注意事项:敬请期待!很快 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

这样性能会好很多:

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

解决方案 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

3 个词在 7 秒内 - 不错。

解决方案 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

LOWER() 比较慢。请改用正则表达式 (?i) 修饰符。

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

【讨论】:

感谢 Elliot Brossard 的提示! 更短的解决方案 2(类似性能):REGEXP_CONTAINS(text, '(?i)(big( )?query|google cloud)') 是的 - 但只是因为我为这个例子选择了类似的字符串:)

以上是关于提高 BigQuery 不区分大小写的搜索性能的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery 中的函数名称区分大小写

如何在不区分大小写的 MySQL 数据库上执行区分大小写的搜索?

如何将 Presto 搜索配置为不区分大小写?

grails中不区分大小写的搜索

使用“/”和“ - ”进行不区分大小写的搜索

不区分大小写的搜索