【问题标题】:Alternative to BigQuery for medium-sized data中型数据的 BigQuery 替代方案
【发布时间】:2017-08-01 10:56:30
【问题描述】:

这是问题Why doesn't BigQuery perform as well on small data sets 的后续内容。

假设我有一个大约 1M 行的数据集。在我们使用(mysql)的当前数据库中,聚合查询运行速度非常慢,可能需要大约 10 秒左右的复杂聚合。在 BigQuery 上,所需的初始化时间可能使这个查询需要大约 3 秒,比在 mysql 中要好,但是如果我们需要在 1 秒或更短的时间内返回查询,则该工作的工具是错误的。

然后我的问题是,在对中等大小的数据集(例如 1-10M 行)进行聚合查询时,除了使用 BigQuery 之外,还有什么好的替代方法?一个示例查询可能是:

SELECT studio, territory, count(*)
FROM mytable
GROUP BY studio, territory
ORDER BY count(*) DESC

我想到的可能解决方案是 ElasticSearch (https://github.com/NLPchina/elasticsearch-sql) 和 Redshift(postgres 太慢)。在这里可以通过 SQL 查询的好选择是什么?

注意:我不是在寻找 why如何 BQ 应该被使用,我正在寻找查询可以在 10M 行以下的数据集的替代方案在约 1 秒内返回。

【问题讨论】:

  • @David542 像 Redshift 和 Bigquery 这样的 OLAP 系统在构建时并不强调快速查询处理,这些系统常见的多秒甚至一分钟查询。有了你提到的数据量,你应该能够在 Redshift 之类的东西上实现它,但我很确定这种延迟会有多一致。也许您应该考虑不同的架构,例如放置一个缓存来提供分析查询的结果,然后安排定期运行您的查询以更新您的缓存。
  • @cpard 同意,在我们对“小”数据大小的 Redshift 进行的测试中,它始终表现更差,有时临时查询在第一次执行时会花费 20 多秒,请参阅docs.aws.amazon.com/redshift/latest/dg/c-query-performance.html
  • @cpard,对,我们正在做 x3 基准测试,所以第一次会更长,但接下来的两次有编译查询。无论如何,这对我们的项目来说是一个杀手,因为大多数查询都是临时的,我们不能有免责声明,“别担心——你的查询需要 20 秒,但第二次运行它会更快!”
  • @David542 如果您不介意使用非 SQL 的查询语言,那么在有此类要求的情况下使用 Elastic Search 可能会更好。特别是如果您计划让多个并发用户运行查询。您知道 Redshift 的并发查询限制吗? docs.aws.amazon.com/redshift/latest/dg/…
  • @David542 我添加了一些我个人实际使用过的替代方案的答案。我对您的 Redshift 体验感到有些惊讶。您使用的是什么类型的节点和表结构?我们经常在我们的 SSD 节点上看到亚秒级的查询,无论之前是否有查询。

标签: mysql sql google-bigquery amazon-redshift


【解决方案1】:

2020 年更新:查看 BigQuery BI Engine,它是仪表板查询的内置加速器:


如果您需要在一秒钟内获得答案,则需要考虑编制索引。

典型故事:

  1. MySQL(或此处建议的任何其他数据库)速度很快,直到...
  2. 有一天,您的一些聚合查询开始运行缓慢。分钟、小时、天等。
  3. 第 2 步的典型解决方案是索引和预聚合。如果您希望在不到一秒的时间内回答特定类型的问题,则需要投入时间和优化周期来回答此类问题。
  4. BigQuery 的优点在于您可以跳过第 3 步。以最少的投资将这些分钟/小时/天缩短为秒 - 任何查询,任何时间。

BigQuery 很棒,因为它给了您 4 个。但是您要求 3 个,MySQL 很好,Elasticsearch 也很好,任何索引数据库都会在不到一秒的时间内为您带来结果 - 只要您投入时间针对特定类型的问题优化您的系统。然后,要在不投入任何优化时间的情况下获得任意问题的答案,请使用 BigQuery。

BigQuery:将在几秒钟内回答任意问题,无需准备。

MySQL 和替代方案:将在不到一秒的时间内回答某些类型的问题,但需要开发时间才能到达那里。

【讨论】:

  • 感谢您。出于好奇,当谷歌需要在聚合数据集(例如谷歌分析)上获得亚秒级响应时,他们会做什么?我会假设他们没有使用 BigQuery 或类似的(可能不是 mysql 或传统的 oltp 系统)?
  • Google Analytics 是否曾在不到一秒的时间内展示其图表? (这是一个提示)
【解决方案2】:

如果您正在寻找亚秒级的 OLAP 查询结果,那么 Druid (http://druid.io/) 就是为此目的而构建的。它是一个部署和调整的野兽,但是一旦你为你的数据正确配置了它,它就会非常非常快。它具有流式支持,因此您可以从 Kafka 中提取一次语义,这非常棒。它可以很好地从少量数据扩展到大量数据 - 尽管您会在进行预聚合时付出一定的代价,因此如果您有很多维度,数据大小会爆炸。 SQL 支持是最近才添加的,而且还不完整。此外,它不支持连接,因此您必须正确构建数据才能得出答案。

【讨论】:

  • 谢谢,我们测试了 Druid,它对我们的需求没有用处。它需要一个带时间戳的字段,而我们的数据通常没有(或需要):“Druid 中的每一行都必须有时间戳。数据总是按时间分区,每个查询都有时间过滤器。查询结果也可以被破坏按分钟、小时、天等时间段递减。” -- druid.io/docs/0.9.2/ingestion/schema-design.html
  • 是的,这是真的。可以通过构建一个用于分区的长值来解决此问题,但如果您的数据本质上不是时间序列,则最好使用其他东西。
  • 小数据的另一个选择可能是像 apache ignite 这样的数据网格。记住这一切,它应该会快速尖叫。我没用过,但我知道它支持 sql 并且可以与 Tableau 等 BI 工具配合使用。有相当多的类似产品可能具有相似或更出色的功能。
  • 这很有趣,我从未使用过(甚至听说过)apache ignite。你知道任何使用它的产品或测试它的好方法吗?
【解决方案3】:

您很少谈论您所处的问题空间 - 但您是否考虑过 python pandas 或 R?这些是用于数据分析/开发的绝佳工具。

假设你有方便的 python 和 pandas pip install pandas 你可以开始使用这样的东西:

import pandas as pd
import pyodbc

conn = pyodbc.connect(...) # You'll need to figure out the settings for your DB here
# this slow but only needs to be done once:
data = pd.read_sql_query('select * from mytable') # Load everything into memory 

# Now do the query:
data.groupby(['studio', 'territory']).count().sort_values(ascending=False)

我强烈建议使用 Jupyter Notebooks 试用 pandas

【讨论】:

    【解决方案4】:

    我的答案:优化查询和表结构,如前所述(1 秒或更短)。请继续阅读以下内容以获取进一步的推理,因为我们都陷入了这个陷阱。注:以上不一定是大数据集。

    一个很好的问题。破译什么是问题以及什么是解决方案是一项艰巨的任务。这是一个来自老学校的镜头。在过去,我们常说您询问硬件、操作系统或开发人员问题/解决方案是什么,您会得到三个不同的答案。

    我的理解是这个问题要求解决/比较 SQL 性能问题与云基础设施解决方案。这个问题会根据背景有很多不​​同的答案。令人困惑的是,您只有老式的数据库安装(Mysql、Oracle、MSsql)、数据库即服务(DBAAS)、大数据云解决方案、大数据应用解决方案(hadoop)

    很容易纠缠于所有这些技术。也许这里有点清楚。

    SQL 性能问题可以通过多种性能点(POP)来解决。

    1. SQL 优化和调优(临时表、内存中、OLAP 函数、Sql 计划、并行化、分析)工具(MySql Workbench、cmdline、Toad 等)
    2. 结构优化(表、索引、分区、Pre-Ag 结构)
    3. 数据库配置(内存大小、缓存大小、并行化、块大小等。
    4. 操作系统内存、页面大小、进程)
    5. 硬件和网络 - 现在几乎不重要了。
    6. 服务器配置。
    7. 云配置和集群。
    8. 基础设施和软件决策。

    底线:我会停在这里,我们有很多解决问题的方法。尝试从技术的最基本用法开始,然后再使用更大的技术解决成本问题。希望这将为用户提供一个工作路径的框架或在提出问题时使用的术语。如何让 x 查询在时间 t 内运行?

    【讨论】:

      【解决方案5】:

      对于这种大小的数据,可以考虑以下几种替代方法:

      1. 单个 Redshift 小型 SSD 节点
        • 没有设置。在 1 秒内轻松返回大量数据的答案。
      2. 小型 T2 实例上的 Greenplum
        • 类似 Postgres。与 Redshift 类似的性能。不为不需要的存储付费。从他们的单节点“沙盒”AMI 开始。
      3. MariaDB 列存储
        • 类似于 MySQL。曾经被称为 InfiniDB。非常好的表现。由 MariaDB(公司)提供支持。
      4. 阿帕奇钻
        • Drill 的理念与 BiqQuery 非常相似,但可以用于任何地方(它只是一个罐子)。对这种大小的数据进行查询会很快。

      如果低管理员/快速入门至关重要,请使用 Redshift。 如果资金/灵活性至关重要,请从 Drill 开始。 如果您更喜欢 MySQL,请从 MariaDB Columnstore 开始。

      【讨论】:

      • 感谢这些建议。我们尝试了 Drill,它运行良好,但在基准测试中,Impala 的表现比 Drill 更好/更快。由于硬并发限制,Redshift 也不是一个选项(如问题 cmets 之一所述)-docs.aws.amazon.com/redshift/latest/dg/…。将检查 Greenplum 和 MariaDB。
      • 黑斑羚,嗯。 ? 如果您愿意使用那种 工具,那么一定要看看 Spark - 良好的 SQL 支持,您的数据将很容易放入内存中。也看看 Clickhouse。 tech.marksblogg.com/billion-nyc-taxi-clickhouse.html
      • 是的,我们还测试了 Spark 和 Clickhouse。 Impala 的性能比 Spark 好,而且 Clickhouse 有一些限制,使其不适合我们的项目(没有预先知道数据性质的情况下不接受任何参数的高效引擎——clickhouse.yandex/reference_en.html#Table 引擎)。将让您了解 Greenplum 或 MariaDB 的工作原理。
      • 这里是我们在应用程序中使用的实际查询,在我们用于初始加载/测试的 1000 行数据集上,第一次查询耗时 16 秒,然后全部查询耗时约 600 毫秒其他查询:
      • 嗯,我并没有真正理解该查询试图做什么。我想说的是,COUNT(DISTINCT 通常是 MPP DB 上的性能杀手。
      【解决方案6】:

      不要使用COUNT(*)

      在单个列上使用COUNT(),最好是像PRIMARY KEY 这样的索引列。

      【讨论】:

      • COUNT(*) 计算行数并让优化器灵活地选择要使用的索引COUNT(x) 检查每个x 是否为NOT NULL,这通常是不希望的。
      • COUNT(*) 表示计算所有未充满NULL 值的行。许多实现使用全表扫描来做到这一点。
      • 我坚信你对COUNT(*) 需要查看所有列是错误的。我尝试了一个所有列都可以为空的简单表; COUNT(*) 包括所有为空的行。
      【解决方案7】:

      如果这是您唯一的查询,那么这将使它运行得更快:

      INDEX(studio, territory)  -- in either order.
      

      如果还有其他变体,让我们看看它们,加上SHOW CREATE TABLE

      另一件要检查的事情:你有多少 RAM,innodb_buffer_pool_size 的值是多少?该设置应该是 RAM 的 70% 左右(如果您的 RAM 超过 4GB)。

      【讨论】:

      • 谢谢,以上只是一个示例查询,所以我们不一定知道要使用的索引组合。
      • 需要看到问题的广度才能提供完整的解决方案。声音链接了一个“EAV”问题——这很混乱。
      【解决方案8】:

      我知道 SQL Server,所以我的回答是有偏见的。

      1. 10M 行应该很容易放入内存中,因此任何类型的聚合都应该很快,尤其是在您有覆盖索引的情况下。如果没有,服务器配置可能需要调整。另外,SQL Server 有所谓的in-memory tables,在这里可能很适合。

      2. SQL Server 有一个名为indexed view 的功能。您的聚合查询是索引视图的经典用例。索引视图本质上是存储在磁盘上的数据的副本,并在表中的基础数据发生变化时由服务器自动维护。它减慢了 INSERTS、DELETES 和 UPDATES,但使 SELECT 更快,因为总是预先计算摘要。请参阅:What You Can (and Can’t) Do With Indexed Views。其他 DBMS 应该具有类似的功能。

      【讨论】:

      • 我们在六个应用程序查询上对 SQLServer 进行了基准测试,它在大约 1M 行及以下的行上看起来不错。在那之后,6 个查询中的 5 个可能超出了我们的可用内存并且非常慢。我认为 SQLServer 将是大约 1M 行或以下的选项,但在更复杂的查询中,它很快就会超过机器内存(即使我们得到更大的机器)。
      • @David542,每行 100 字节的 10M 行是 1GB。它不是微不足道的小,但也不是太大。您可能需要查看执行计划并检查服务器在做什么。如果您使用索引视图,您应该能够大大减少服务器需要读取/保存在内存中的数据量(取决于您的数据)。如果原始完整表有 10M 行,但只有 10K 个不同的 studio, territory 组合,那么索引视图的索引将只有 10K 行 => 使用索引视图的查询会非常快。
      • @David542,另一方面,如果整个表有 10M 行并且有 9M 不同的 studio, territory 组合,那么索引视图将无济于事。 (studio, territory) 上的简单索引将产生几乎相同的效果。
      【解决方案9】:

      BigQuery 旨在在大数据管道的末端发挥最佳性能。它的设计目的是在处理大型数据集而不是小型数据集时表现良好,并且不是为了替代现有技术,而是在某些情况下作为一个很好的补充。可以在“Google Cloud 大数据和机器学习博客”document 中阅读示例。

      【讨论】:

        【解决方案10】:

        我认为Microsoft SQL Server Analysis Services是一个不错的选择,我自己用过,它是PowerBI服务背后的数据库,有一个非常好的免费层选项。

        如果你想要一个免费的本地解决方案,你总是可以使用带有新列存储技术的 SQL Server express,我自己没有使用它,但我听说了一些非常好的结果

        【讨论】:

          【解决方案11】:

          如果您不需要并发,多个用户同时连接,并且您的数据可以放在一个磁盘文件中,那么 SQLite 可能是合适的。

          正如他们所说,SQLite 不与客户端/服务器数据库竞争。 SQLite 与 fopen() 竞争。

          http://www.sqlite.org/whentouse.html

          【讨论】:

          • 我们需要这个并发。我认为 Impala 可能是最快的选择,但对于
          猜你喜欢
          • 2021-11-18
          • 1970-01-01
          • 1970-01-01
          • 2012-08-15
          • 1970-01-01
          • 1970-01-01
          • 2012-08-21
          • 2011-03-18
          • 1970-01-01
          相关资源
          最近更新 更多