如何改善大数据应用程序的表和查询?

时间:2018-08-30 06:25:16

标签: mysql symfony doctrine-orm bigdata

我在Symfony上创建了一个API,该API每天向其中一个MySql表中生成超过100万个条目。该表结构是通过以下方式定义的:

enter image description here

使用几周后,该表已经有3500万(不是万亿)行。当我查询该表时,像这样的简单查询的响应时间将近20秒:

public function findAllCryptosByRank($date_minute)
{
    $query = $this->_em->createQueryBuilder()
        ->select("cm")
        ->from("APIBundle:CoinmarketcapSnapshot", "cm")
        ->where("cm.date_minute = :date_minute")
        ->orderBy("cm.rank", "ASC")
        ->setMaxResults(10)
        ->setParameters(array(
            'date_minute' => $date_minute,
        ));
    $finalQuery = $query->getQuery();
    return $finalQuery->getArrayResult();
}

做更复杂的事情时,甚至会更糟;查询耗时超过一分钟。例如,类似这样的东西:

public function findAllCryptosByRank($date_minute,$date_hour,$date_day,$date_month,$date_year)
{
    $query = $this->_em->createQueryBuilder()
        ->select("cm", "c.logo", "c.title")
        ->from("APIBundle:CoinmarketcapSnapshot", "cm")
        ->where("cm.date_minute = :date_minute")
        ->andWhere("cm.date_hour = :date_hour")
        ->andWhere("cm.date_day = :date_day")
        ->andWhere("cm.date_month = :date_month")
        ->andWhere("cm.date_year = :date_year")
        ->leftJoin(
            'APIBundle:Cryptocurrency',
            'c',
            \Doctrine\ORM\Query\Expr\Join::WITH,
            'cm.cryptocurrency__id = c. coinmarketcap_id'
        )
        ->orderBy("cm.rank", "ASC")
        ->setMaxResults(10)
        ->setParameters(array('date_minute'=>$date_minute,'date_hour'=>$date_hour,'date_day'=>$date_day,'date_month'=>$date_month,'date_year'=>$date_year))
    ;
    $finalQuery = $query->getQuery();
    return $finalQuery->getArrayResult();
}

那么,我该怎么做才能大大提高这些性能?我读到了有关Doctrine的文章,该文章不是为大数据用例而设计的。

我知道可以通过使用诸如Hadoop之类的工具或优化索引来提高MySQL性能。

但是就目前的低表现而言,这够了吗?

我想确保Symfony是此应用程序的不错选择。我正在考虑将API迁移到另一个后端框架,例如ASP.NET或Node.JS。你觉得呢?

2 个答案:

答案 0 :(得分:3)

首先,您不应该将教义视为Symfony不可分割的一部分。您可以随意删除它并切换到其他ORM实施,也可以跳过Doctrine ORM,而只使用DBAL。另外,有时消除ORM或iterating the result sets的开销可能会为您带来性能提升。

第二,这与Symfony或Doctrine无关,实际上与在应用程序中组织数据的方式有关。您应该问的问题是您是否使用正确的工具来完成工作。如几条评论中所建议,您可以完全切换存储(例如,使用ElasticSearch作为存储)。

当然,您也绝对应该使用典型的查询优化技术(例如,运行EXPLAIN查询并查看瓶颈在哪里)。

答案 1 :(得分:1)

  • 了解有关编制索引的信息。那个特定的查询(看起来很奇怪)需要`INDEX(date_minute,rank)。
  • 算一算:几周内没有磁盘可以容纳35万亿行。
  • 您的AUTO_INCREMENT的上限为20亿。那将不支持35万亿行。
  • 请勿将日期/时间值分成多列。
  • 对于1字节数量(例如“ date_minute”),请不要使用4字节INT。参见TINYINT UNSIGNED
  • 将数字数据类型(而非LONGTEXT)用于数字值(交易量,市值等)。
  • 除非您期望对这些列进行任何操作,否则不要包括createdupdated。 (第三个软件包似乎喜欢生成它们,但是不要使用它们。)

我要处理数据类型,因为表会变得很大;尽可能缩小数据类型将有助于使其适合您的有限磁盘,并有助于加快查询速度。