Я создал API на Symfony, который ежедневно производит более 1 миллиона записей в одну из таблиц MySql. Эта структура таблицы определяется следующим образом:
После нескольких недель использования таблица содержит уже 35 миллионов (не триллион) строк. И когда я запрашиваю эту таблицу, время ответа составляет почти 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, которая не была разработана для случаев использования больших данных.
Я знаю, что можно улучшить производительность MySQL, используя такие инструменты, как Hadoop, или, например, оптимизируя индексы.
Но будет ли этого достаточно для очень низких показателей на данный момент?
Я хочу быть уверен, что Symfony - хороший выбор для этого приложения. Я рассматриваю возможность переноса API на другую Backend Framework, такую как ASP.NET или Node.JS. Что вы думаете?
прежде всего убедитесь, что запрос использует правильный индекс или можно ли его оптимизировать.
Я думаю, вам следует беспокоиться не о структуре, а о самой базе данных. Вам понадобится база данных для больших данных, если вы планируете работать с триллионом записей. Вы можете легко получить доступ к другим базам данных помимо MySQL в Symfony, и вы можете применить отличные оптимизации, но MySQL в конечном итоге станет узким местом
При использовании всего миллиона строк в день потребуется 95 890 века для накопления 35 триллионов строк!






Во-первых, вы не должны относиться к Doctrine как к неотъемлемой части Symfony. Вы можете удалить его и переключиться на другую реализацию ORM или, возможно, пропустить Doctrine ORM и просто использовать вместо этого DBAL. Кроме того, иногда удаление накладных расходов ORM или итерация наборов результатов может дать вам повышение производительности.
Во-вторых, речь идет не о Symfony или Doctrine, а о том, как вы организовываете данные в своем приложении. Вам следует задать вопрос, используете ли вы правильный инструмент для работы. Как было предложено в нескольких комментариях, вы можете полностью переключить хранилище (например, использовать ElasticSearch в качестве хранилища).
А также вам обязательно следует использовать типичные методы оптимизации запросов (например, запустить запрос EXPLAIN и посмотреть, где узкое место).
Автор не использует хороших инструментов для управления большими данными ... Php или MySQL - хороший выбор.
@russellhoff, какой фреймворк вы предлагаете для случаев использования больших данных?
@kix, я знаю, что Doctrine не является обязательной при использовании Symfony, но я выбрал Symfony помимо Laravel, особенно для Doctrine, потому что мне это нравится. Я не знал, что это плохо для выступлений с большими данными
Я бы не выбрал PHP для больших данных из-за природы PHP. Вам нужен язык, который позволяет управлять миллионами записей, и PHP определенно не лучший выбор, поскольку он имеет максимальное время выполнения для каждого скрипта. Я бы выбрал такие языки, как Java или Python. А что касается базы данных, выберите любую, кроме MySQL.
AUTO_INCREMENT имеет ограничение в 2 миллиарда. Это не поддерживает 35 триллионов строк.INT для 1-байтовых величин, таких как date_minute. См. TINYINT UNSIGNED.LONGTEXT) для числовых значений (объем, рыночная капитализация и т. д.).created и updated, если вы не собираетесь что-либо делать с этими столбцами. (Кажется, что третьим пакетам нравится их генерировать, но потом не используйте их.)Я говорю о типах данных, потому что таблица станет очень большой; сжатие типов данных, где это возможно, поможет им уместиться на вашем ограниченном диске и ускорит запросы.
Да, правда, не 35 триллионов, а фактически 35 миллионов. Я могу подтвердить первый пункт, после того как я добавил индекс в столбец «ранг», тот же запрос теперь занимает менее 1 секунды.
Лучший способ сделать это - использовать elasticsearch.