Как улучшить мои таблицы и запросы для приложений с большими данными?

Я создал 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. Что вы думаете?

Лучший способ сделать это - использовать elasticsearch.

mlivan 30.08.2018 08:45

прежде всего убедитесь, что запрос использует правильный индекс или можно ли его оптимизировать.

Matteo 30.08.2018 08:52

Я думаю, вам следует беспокоиться не о структуре, а о самой базе данных. Вам понадобится база данных для больших данных, если вы планируете работать с триллионом записей. Вы можете легко получить доступ к другим базам данных помимо MySQL в Symfony, и вы можете применить отличные оптимизации, но MySQL в конечном итоге станет узким местом

mpilliador 30.08.2018 09:06

При использовании всего миллиона строк в день потребуется 95 890 века для накопления 35 триллионов строк!

Rick James 31.08.2018 06:41
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
1
4
610
2

Ответы 2

Во-первых, вы не должны относиться к Doctrine как к неотъемлемой части Symfony. Вы можете удалить его и переключиться на другую реализацию ORM или, возможно, пропустить Doctrine ORM и просто использовать вместо этого DBAL. Кроме того, иногда удаление накладных расходов ORM или итерация наборов результатов может дать вам повышение производительности.

Во-вторых, речь идет не о Symfony или Doctrine, а о том, как вы организовываете данные в своем приложении. Вам следует задать вопрос, используете ли вы правильный инструмент для работы. Как было предложено в нескольких комментариях, вы можете полностью переключить хранилище (например, использовать ElasticSearch в качестве хранилища).

А также вам обязательно следует использовать типичные методы оптимизации запросов (например, запустить запрос EXPLAIN и посмотреть, где узкое место).

Автор не использует хороших инструментов для управления большими данными ... Php или MySQL - хороший выбор.

russellhoff 30.08.2018 09:12

@russellhoff, какой фреймворк вы предлагаете для случаев использования больших данных?

Kr1 30.08.2018 09:29

@kix, я знаю, что Doctrine не является обязательной при использовании Symfony, но я выбрал Symfony помимо Laravel, особенно для Doctrine, потому что мне это нравится. Я не знал, что это плохо для выступлений с большими данными

Kr1 30.08.2018 09:32

Я бы не выбрал PHP для больших данных из-за природы PHP. Вам нужен язык, который позволяет управлять миллионами записей, и PHP определенно не лучший выбор, поскольку он имеет максимальное время выполнения для каждого скрипта. Я бы выбрал такие языки, как Java или Python. А что касается базы данных, выберите любую, кроме MySQL.

russellhoff 30.08.2018 12:04
  • Узнайте об индексировании. Этот конкретный запрос (который кажется странным) требует `INDEX (date_minute, rank).
  • Посчитайте: не существует диска, который мог бы принять 35 триллионов строк за несколько недель.
  • Ваш AUTO_INCREMENT имеет ограничение в 2 миллиарда. Это не поддерживает 35 триллионов строк.
  • Не разбивайте значения даты и времени на несколько столбцов.
  • Не используйте 4-байтовый INT для 1-байтовых величин, таких как date_minute. См. TINYINT UNSIGNED.
  • Используйте числовые типы данных (не LONGTEXT) для числовых значений (объем, рыночная капитализация и т. д.).
  • Не включайте created и updated, если вы не собираетесь что-либо делать с этими столбцами. (Кажется, что третьим пакетам нравится их генерировать, но потом не используйте их.)

Я говорю о типах данных, потому что таблица станет очень большой; сжатие типов данных, где это возможно, поможет им уместиться на вашем ограниченном диске и ускорит запросы.

Да, правда, не 35 триллионов, а фактически 35 миллионов. Я могу подтвердить первый пункт, после того как я добавил индекс в столбец «ранг», тот же запрос теперь занимает менее 1 секунды.

Kr1 01.09.2018 12:57

Другие вопросы по теме