Чем дальше ты двигаешься, тем большую ответственность приходится брать и тем больше решений приходится принимать. В определенный момент абсолютная уверенность пропадает, как категория, но взамен приходит искусство баланса вслед за смелостью делать шаг.
Синдром самозванца. А что если меня разоблачат? Конечно разоблачат, если ничего не делать. Если делать важное, то через время замечаешь, что разоблачать тебя уже некому.
Эта похожа на «если долго сидеть на берегу реки, то можно увидеть, как по ней проплывет труп твоего врага». :)
Похоже, что hoverfly призван помочь в тестировании тем, что заменяет собой внешние зависимости по отношению к тестируемому сервису, имитирует их ответы.
Gonkey, в отличие от goverfly, ставит перед собой цель тестировать сам сервис, то есть имитировать клиентскую нагрузку на него. А чтобы заменять ответы внешних сервисов, в gonkey есть моки.
При штатном режиме работы базы и приложения пул соединений в Go позволяет не порождать новые соединения к базе. А вот при малейшей деградации базы данных пул соединений на стороне приложения исчерпывается и кол-во порождаемых соединений на единицу времени в разы возрастает.
А можете прояснить, какая тут причинно-следственная связь?
Не нужно так уж привязываться к задаче, она наполовину выдуманная и нужна, чтобы проиллюстрировать использование курсора. Суть проблемы в том, что нужно выкачать из базы много данных и использовать при этом предсказуемое количество памяти.
Какие шаги предпринимает Doctrine, чтобы достать из базы, например, 5000 объектов заказа?
1. Делает запрос в базу
2. Выкачивает 5000 строк
3. Делает Hydration — то есть раскладывание сырых данных в объекты (или массивы, есть разные режимы гидрации)
4. Отдает тебе массив из 5000 объектов заказа
Какой шаг позволяет оптимизировать использование iterate()? Только третий — гидрацию. Он позволяет не гидрировать 5000 объектов за раз, а делать это один за другим. Да, это дает значительную экономию памяти. Но Doctrine при этом все равно выкачивает все 5000 строк в память приложения, прежде чем начать их итерировать.
Описанный в статье подход позволяет оптимизировать не третий шаг, а второй. То есть получать данные из базы постепенно. И, само собой, гидрация в таком подходе тоже будет постепенной — будут обрабатываться только скачанные в эту итерацию строчки.
Чтобы сделать fetch() в PDO, данные уже должны быть в памяти приложения. Именно так PDO работает по умолчанию. То есть, fetch() извлекает одну строку не из сервера, а из собственного буфера.
Можно перед fetch() сделать prepare() с атрибутом ATTR_CURSOR, тогда будет использоваться серверный курсор (ему и посвящена статья), и только тогда данные действительно будут выкачиваться с сервера строка-за-строкой.
2Гис я использовал только для иллюстраций к презе (это не настоящие скриншоты), так-то у нас в основном Яндекс.Карты (по лицензии). Из OpenstreetMap мы пополнили базу домами для Украины и Белоруссии, а также координатами домов для всех стран.
1. Сейчас уже и не смогу ответить так, чтобы звучало аргументировано. Думаю, решение о выборе Solr-а принималось на основе того, что у нас был хороший опыт его использования для каталога товаров. Работает быстро: простые запросы 1-2 мс, запросы посложнее (например, с проверкой вхождения точки в полигон) — 20-30 мс. Железа много не требует.
2. Не совсем понял вопрос. Отвечу как понял. Например, если ввести «Новгоро», то в саджесте будет «Нижний Новгород», да.
3. Да, есть хинт по улицам. А мусор — это что? Если речь про разные объекты, которые в ФИАС притворяются улицами, то самые назойливые кейсы исправляем точечными переопределениями их «уровня в иерархии».
4. Вроде бы Яндекс.Карты, но зуб не дам (давно не видел этот интерфейс).
5. Не скажу, что в нашем коде не может встретиться чего-то такого, но вот конкретно CitiName — не наше изобретение :) Это поле из API одной из служб доставки.
Особенно понравилась пара цитат:
Эта похожа на «если долго сидеть на берегу реки, то можно увидеть, как по ней проплывет труп твоего врага». :)
Gonkey, в отличие от goverfly, ставит перед собой цель тестировать сам сервис, то есть имитировать клиентскую нагрузку на него. А чтобы заменять ответы внешних сервисов, в gonkey есть моки.
(но, признаюсь, я действительно сделал эту ошибку, когда писал этот демо-код)
А можете прояснить, какая тут причинно-следственная связь?
Какие шаги предпринимает Doctrine, чтобы достать из базы, например, 5000 объектов заказа?
1. Делает запрос в базу
2. Выкачивает 5000 строк
3. Делает Hydration — то есть раскладывание сырых данных в объекты (или массивы, есть разные режимы гидрации)
4. Отдает тебе массив из 5000 объектов заказа
Какой шаг позволяет оптимизировать использование iterate()? Только третий — гидрацию. Он позволяет не гидрировать 5000 объектов за раз, а делать это один за другим. Да, это дает значительную экономию памяти. Но Doctrine при этом все равно выкачивает все 5000 строк в память приложения, прежде чем начать их итерировать.
Описанный в статье подход позволяет оптимизировать не третий шаг, а второй. То есть получать данные из базы постепенно. И, само собой, гидрация в таком подходе тоже будет постепенной — будут обрабатываться только скачанные в эту итерацию строчки.
www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/batch-processing.html#iterating-large-results-for-data-processing
Можно перед fetch() сделать prepare() с атрибутом ATTR_CURSOR, тогда будет использоваться серверный курсор (ему и посвящена статья), и только тогда данные действительно будут выкачиваться с сервера строка-за-строкой.
Про дополнительную нагрузку на базу с удовольствием бы почитал. Дадите ссылку?
> Предполагается, что этот метод пишет сразу на диск, а не накапливает строки где-то в памяти для последующей записи, я правильно понимаю?
Да, это очень важно, чтобы при записи файла тоже не было буферизации. Как вот здесь, например.
Любим, да не очень, как видите :)
То есть, что-то исправлено, но все исправить — чертовски сложно.
Используем для этого PostGIS, модуль для PostgreSQL.
Так у нас объявлена колонка в таблице для хранения полигона:
А вот так проверяется попадание точки в полигон:
2. Не совсем понял вопрос. Отвечу как понял. Например, если ввести «Новгоро», то в саджесте будет «Нижний Новгород», да.
3. Да, есть хинт по улицам. А мусор — это что? Если речь про разные объекты, которые в ФИАС притворяются улицами, то самые назойливые кейсы исправляем точечными переопределениями их «уровня в иерархии».
4. Вроде бы Яндекс.Карты, но зуб не дам (давно не видел этот интерфейс).
5. Не скажу, что в нашем коде не может встретиться чего-то такого, но вот конкретно CitiName — не наше изобретение :) Это поле из API одной из служб доставки.