我在Symfony上创建了一个API,它每天在一个MySql表中生成超过100万个条目。此表结构以这种方式定义:
经过几周的使用,该表已经有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.你怎么看?
首先,你不应该将Doctrine视为Symfony不可分割的一部分。您可以自由删除它并切换到不同的ORM实现,或者可以跳过Doctrine ORM而只是使用DBAL。此外,有时删除ORM或iterating the result sets的开销可能会提升性能。
其次,这与Symfony或Doctrine无关,这实际上与您在应用程序中组织数据的方式有关。您应该问的问题是,您是否使用正确的工具来完成工作。正如几条评论中所建议的那样,您可以完全切换存储(例如,使用ElasticSearch作为存储)。
而且你肯定应该使用典型的查询优化技术(比如,运行EXPLAIN
查询并查看瓶颈在哪里)。
AUTO_INCREMENT
有20亿的限制。这将不会支持35万亿行。INT
用于1字节数量,例如“date_minute”。见TINYINT UNSIGNED
。LONGTEXT
和created
,除非您希望对这些列实际执行任何操作。 (第三个包似乎喜欢生成它们,但是不要使用它们。)我在数据类型上喋喋不休,因为表格会变得非常大;尽可能缩小数据类型将有助于它适合您的有限磁盘,并有助于加快查询速度。