• Как лучше всего организовать очистку файла журнала в PostgreSQL?

    batyrmastyr
    @batyrmastyr
    1) Как советует Александ Путров, классический путь: интересующие события пишите в таблицу.
    2) Если нужны уведомления подписчиков, то ставите Supabase Realtime. Это отдельный сервис который прикидывается репликой постгреса и рассылает уведомления клиентам.

    поэтому варианта очистки лог-файла через PostgreSQL я не нашел

    Это вредная идея уровня «мне сборщик мусора в JAVA не даёт сразу очистить мусор, я хочу подключаться из другого процесса и делать очистку сам», никогда так не делайте.
    Ответ написан
    Комментировать
  • Можно ли организовать фильтр/поиск товаров посредством JSON_EXTRACT?

    batyrmastyr
    @batyrmastyr
    Сделать можно, но здесь вас ждёт множество граблей:
    1. Крайне неэффективное хранение: объём в разы больше, чем если раскидать по таблицам.
    2. Эффективность индексов по JSON полю: если в постгресе она не особо радует, но можно выбирать между простотой и скоростью работы, то в мускуле есть только убогие костыли с индексированием частей объекта через генерируемые столбцы.
    3. OR = JSON_OVERLAPS, IN = JSON_CONTAINS или разворачивать вручную. И чёрт знает, сработает ли индекс потому, что это функции, а не операторы.
    4. Типизация значений: в JSON можно пихнуть и '3', и 3 и 3.0. Нужно внимательно следить за типами и при сохранении, и при поиске, чтобы всё правильно находилось.

    В общем, если хотите навернуть такое, то стоит крепко задуматься о переходе на постгрес, в нём хотя бы 2 и 3 проблемы не будут выглядеть неразрешимыми.
    Ответ написан
    Комментировать
  • Ошибка trying to access array offset on value of type null in?

    batyrmastyr
    @batyrmastyr
    Isset, причём в форме
    $options = $this->tree["main"]["home"]["options"] ?? $this->tree["main"]["options"] ?? $this->tree["all"]["options"];

    Но сперва прикинуть какой из уровней оказывается null вместо массива: $this->tree["main"]["home"], $this->tree["main"] или $this->tree и насколько такая ситуация нормальна?
    Ответ написан
    2 комментария
  • Какой стэк использовать для быстрого доступа данных?

    batyrmastyr
    @batyrmastyr
    1) > чтобы хранить весь массив данных в виде json
    JSON уже давно можно хранить в самом MySQL, если вам нужно произвольное число параметров, но значения их скалярные. Для индексации - виртуальные колонки и индексы по ним.
    Если хочется найти искать «1» в массиве [1, 2,5], то вам в PostgreSQL.
    2) «Полнотекстовый поиск» — что вы от него хотите? Если вам нужно точное совпадение, только быстрее, то берите что угодно.
    Если вам нужен учёт словоформ, то он есть как минимум в Монге, Эластик, Постгрес, Сфинкс/Мантикора.
    Если вы хотите больше контроля (поиск с учётом особенностей > 1 языка, тюнинг морфологии, какое-то ранжирование), то выкидываем Монгу (нет тюнинга морфологии и ранжирования, а на каждый язык нужно вешать отдельный индекс).
    Если вы и ранжирование хотите тюнить (вплоть до простенького машинного обучения) и вообще максимальную скорость поиска, то вас спасёт только Мантикора/Сфинкс, всё остальные грустно глотают пыль.

    Но золотая середина - Постгрес. На него довольно легко перекатиться и он избавляет от необходимости разводить NoSQL зоопарк.
    P.S. И забудьте про монгу, Постгрес лучше неё почти по всем параметрам.
    Ответ написан
    Комментировать
  • Какие есть вариант ускорить работу Докера на Macbook?

    batyrmastyr
    @batyrmastyr
    Кратко: запускать под линуксом.
    Подробнее: виртуалка на ваш вкус, в ней линукс на выбор, в нём докер. Получите просадку по скорости раза в 1,5 - 2, но (1) это всё равно на порядок лучше говна с названием "докер для мака" (2) грузит проц только когда нужно, а не перманентные 100% на одно из ядер.
    Особенности:
    1. код прокидываете через общую папку.
    Проблемы с пробросом папок:
    1. Поскольку виртуалки делают это как сетевых дисков, отслеживание изменений файлов (gulp/webpack/esbuild - watch) отвалится наглухо.
    2. PostgreSQL не сможет стартов стартует, поэтому файлы БД лежат только внутри линукса.
    3. С Virtual Box были ещё какие-то грабли из-за прав на файлы. Кажется получалось так, что читает он их нормально, а вот создаваться из под докера они не создаются.
    Комбинация из Parallels Desktop 12 (да, давно я его честно купил) и Debian 10 завелась, но пришлось искать инструкцию по установке свежих дополнений/драйверов гостевой ОС. С актуальным Parallels дополнения должны поставиться без приседаний..
    Ответ написан
    Комментировать
  • Является ли порочной практика итеративных попыток сдачи тестировщикам сырых результатов работы?

    batyrmastyr
    @batyrmastyr
    Ваш вопрос стоит поделить на две части.
    1. Итеративная сдача и проверка тестировщиком сама по себе порочной не является, если программисты говорят "часть страницы входа готова (вывожу поля почта и пароль, проверяю пока только что они не пустые, и почта похожа на почту, а проверку по базе ещё не делаю)" или "исправил падение если в почту вбить 1@1@localhost" и тестировщик проверяет, что заявленное сделано как надо + выборочно проверяет, что не сломано то, что работало на предыдущей итерации. Если исправить нужно 10 ошибок, а его после каждой заставляют проверять всё, то нужно давать таким свинтусам по шее.
    2. Подход "сделаем какую-то чушь, пусть наша нянька для даунов (тестировщик) разбирается" абсолютно порочен.
    В вашей ситуации, видимо, проще повысить тестировщика до тестировщика-аналитика: сперва отдаёте ТЗ ему, он пишет тестовый план и в процессе уточняет ТЗ с его автором, берёт с кодеров подписку, что им всё понятно, и только потом они идут кодить.
    Ответ написан
    1 комментарий
  • Стоит ли изучать PHP на Metanit?

    batyrmastyr
    @batyrmastyr
    Не стоит, это кривое обновление какого-то самоучителя из нулевых.
    Примеры из «руководства по php 8»
    1. Установка: «качаем пыху под винду, ставим апач». Зачем апач в 2021 году, если примитивный веб-сервер встроили несколько лет назад?
    2. Константы
    608ade28777c9036143560.jpeg
    А теперь смотрим на изменения в PHP 8:
    Возможность определять константы без учёта регистра была удалена. Третий аргумент define() больше не может быть true.

    3. Под видом «предопределённых констант» подсовывают неполный список «магических констант», потеряли ::class которому уже лет 8.

    В целом, как уже сказал FanatPHP, там слишком много примеров того «норм из нулевых», но сейчас за такое бьют линейкой по рукам.
    Ответ написан
    Комментировать
  • Как правильно работать с большим количеством данных?

    batyrmastyr
    @batyrmastyr
    - получение данных об общем количестве записей для построения пагинации, это SELECT count(id)

    1. count(*), а не count(id)
    2. если вас не сильно интересует абсолютно точное значение для миллионов результатов, то делаете оценку количества, начать проще с EXPLAIN <текст запроса> вы можете получить оценку количества результатов. Мы для себя решили, что если по оценке меньше 50 000 строк, то вслед за этим делаем обычный SELECT count(*) для получения точного количества.
    Потом дергается запрос для получения данных на экспорт

    1. Пожалуй, вам от этого нужно избавляться в первую очередь. Нажал человек на кнопку "экспортировать" - экспортируете, а до этого и дёргаться нет смысла. Фильтры можно получить либо при клике, либо из заголовка referer
    2. Если вам нужно абсолютно все данные, то ставите задание на экспорт в очередь и выполняете его в отдельном процессе, сохраняете в файл. Для пользователя рисуете прогресс выполнения и выводите его в нажатую пользователем кнопку, хотя можно тупо на отдельной странице выводить список "заказанных" выгрузок и ссылки на скачивание.
    Запросы на каждый выпадающий список в фильтрах - SELECT distinct field_name

    Можно с какой-то периодичностью выгружать выхлоп таких запросов в материализованное представление / справочную таблицу / ENUM. Для обновления таких справочников "в реальном времени" можно повесить триггер на вставку в основную таблицу который будет делать INSERT INTO dictionary (value, column_oid) ON CONFLICT / ALTER TYPE ADD VALUE IF NOT EXISTS
    После чего в основной таблице заводите рядом поле под идентификатор в справочнике и индексируете уже его.
    Запрос при фильтрации и сортировке - SELECT * FROM some_table WHERE field_name LIKE '%value%'

    1. если у вас значения длинные (от 8 - 10 символов), то стоит попробовать триграммные индексы. Но на коротких значениях они могут замедлить поиск раза в полтора-два.
    2. Полнотекстовый поиск. В частности есть поиск лексемы по префиксу ts_tsquery('сло:*') (быстро найдёт и "слово" и "словарь", но не найдёт "однословное")
    3. Для полей по которым вы сделаете словари лучше делать поиск через словарь SELECT * FROM table WHERE column_dictionary_id IN (SELECT id FROM dictionary WHERE value LIKE '%текст%'). В словаре у вас наверняка на порядок - три меньше значений, а несколько сотен или тысяч значений в IN постгрес нормально пережуёт.
    Полей много, разные даты, guid, названия проектов, данные из поля типа json, цены.

    Активнее используйте функциональные и частичные индексы.
    Например, у нас есть кадастровые номера. Триграммный индекс по ним весит 56 мбайт, а BTREE по номерам урезанным до кадастровых кварталов - 15 мбайт, в поиске к "cadastre_id LIKE '11:22:333333:1%'" добавился "AND to_quarter(cadastre_id) = '11:22:333333'", но сам поиск получается на порядок быстрее (~5 мсек вместо 50 - 70).
    Главное не забывайте о стоимости этих самых функций - индекс по to_quarter может строиться всего в 1,5 раза дольше нефункционального, если делать LEFT(cadastre, -(position(':' IN reverse(cadastre))), а может и в 100 раз, если использовать регулярку.
    На все индексы не поставишь, тем более что один индекс может добавить гигов 5-10 к весу.

    Если ещё не обновились, то обновляйтесь на 13-ю версию, там размер BTREE индексов уменьшили в 3 раза. Ну и посмотрите, возможно вам где-то нужны GIST, GIN или BRIN индексы.
    Ответ написан
    2 комментария
  • Как преобразовать HTML, JS, CSS в EXE?

    batyrmastyr
    @batyrmastyr
    Если что-то совсем одностраничное, то «сохранить как - mht» в браузере.
    Если покрупнее - то перегнать в chm через htm2chm. Не факт, что вытянет свежий js, но лучше начать с этого, чтобы не тащить 300 метров электрона.
    Ответ написан
    Комментировать
  • Интеграция php с Excel-макросом?

    batyrmastyr
    @batyrmastyr
    1. В сам макрос добавить отправку данных в ваше приложение.
    1б. Если не всем пользователям макроса можно доверять, то вместо отправки из макроса можно выдавать результат работы макроса в JSON, который пользователь сам вставит на сайте.
    2. О том, как мы на PHP запускали настоящий MS Excel ...
    3. Воспользоваться libXL, но она на C++ и обёрток для php вроде бы нет.
    4. Вместо рецепта из варианта 2 можно использовать OLE и из под винды запускать специальный скрипт на php и управлять Экселем.
    Ответ написан
    Комментировать
  • Как узнать высоту всплывающей клавиатуры на мобильных устройствах в браузере (ios)?

    batyrmastyr
    @batyrmastyr
    Попоробуйте использовать VisualViewport - работает начиная с iOS 13, показывает высоты за вычетом высоты клавиатуры.
    Ответ написан
    1 комментарий
  • С помощью каких яп в 2020 делают браузерные игры?

    batyrmastyr
    @batyrmastyr
    С помощью любых транслируемых в WebAssembly, например Unreal Engine уже года три назад добавили поддержку работы в браузерах.
    Ответ написан
    Комментировать
  • Как правильно реализовать ТОП дня, недели, месяца?

    batyrmastyr
    @batyrmastyr
    1. Вместо top_[daily|weekly|monthly] можно завести общую таблицу top со столбцом для признака, что это дневной/недельный/месячный рейтинг.
    2. Обновлять данные в ней раз в день/час.
    3. В транзакции удаляете старые записи и делаете Insert into (select ..., ‘daily’ as type
    INION select ..., ‘weekly’ as type
    INION select ..., ‘montly’ as type
    ).
    При желании можно суточный рейтинг обновлять раз в час, а недельный и месячный раз в сутки.

    Когда rating_log слишком распухнет, можно будет:
    1) секционировать её по времени. Либо встроенными средствами БД, либо вручную перенося старые записи в таблицу-архив.
    2) Воспользоваться более специализированными решениями: расширение timescaleDb для PostgreSQL или колоночную базу типа ClickHouse. Но оба варианта требуют тестирования перед использованием: например, оба не очень любят работу со строками, а Кликхаус предпочитает, чтобы данные вставляли пачками, а не построчно.
    Ответ написан
    Комментировать
  • Старт проекта на NodeJS+MongoDB или PHP+MySQL?

    batyrmastyr
    @batyrmastyr
    Независимо от выбора БД, отделять комментарии от расписаний нужно обязательно и каждый комментарий хранить отдельным документом/строкой. Так вы сможете забирать из базы не всю гипотетическую тысячу сообщений, а только новые.

    Для сообщений в реальном времени: а правда ли вам нужно оно нужно или устроит задержка в 1 - 5 секунд? Если нужно, то стоит посмотреть на модуль HTTP Push Stream для nginx.

    В 2020 чистый JavaScript только для «хренак-хренак и в продакшен» пригоден. Если и выбирать, то между TypeScript / Dart / PHP.

    1) Типизация: PHP / TS / Dart
    2) По скорости: для сайтов с < 200 000 просмотров в сутки даже на классическом php-fpm хватит пары ядер. Но если хочется «чтобы не хуже ноды», то смотрите в сторону swoole, roadrunner, amp и workerman с phpsocket.io.
    3) Возможность писать клиентский и серверный код на одном языке: JavaScript / TypeScript / Dart.

    В роли базы данных лучше возьмите постгрес - он лучше монги почти всем параметрам (скорость почти любых запросов, потребление памяти), только сложные запросы по json у него выглядят, кхм, страшненько. Но уж лучше страшные запросы, чем отдавать монге от 1 гига до 50% оперативки, строить индексы на все подряд поля и несмотря на это терпеть её тормоза.
    Ответ написан
    4 комментария
  • Какие есть альтернативы google аккаунту для хранения контактов?

    batyrmastyr
    @batyrmastyr
    Да тот же Яндекс или можете поднять свой сервер с поддержкой CardDAV .
    Ответ написан
    Комментировать
  • Как организовать пагинацию, если БД и поисковая машина - это раздельные сервисы?

    batyrmastyr
    @batyrmastyr
    1. Попробуйте искать целиком в сфинксе используя распределённые индексы.
    index rss {
    type = distributed
    agent_persistent = 127.0.0.1:9312:rss1
    ...
    agent_persistent = 127.0.0.1:9312:rssN
    agent_persistent = 127.0.0.1:9312:rssUpdates
    }
    В первые N частей закидываете все документы более-менее равномерно их распределив, например, по датам создания или номерам и индексируете редко, раз в сутки или неделю.
    В последний rssUpdates выбираете только документы изменившиеся с последней индексации, прописываете sql_query_killlist чтобы исключить из результатов устаревшие копии документов из других индексов.

    2.1. Точное число результатов довольно быстро можно узнать так из SHOW META:
    "SELECT ... WHERE <условия без сортировки> LIMIT 1; SHOW META like 'total_found';" и смотрите результат второго запроса.

    2.2 Дальше делаете "честные запросы" - фильтрацию, сортировки для получения нужной страницы, но с указанием max_matches: "SELECT .. WHERE ... LIMIT ... OPTION max_matches=страница * размер страницы". В типичной ситуации, когда пользователь угомонится на первых страницах, скорость значительно увеличится.

    3. В третьем сфинксе появился CREATE INDEX для обычных, не текстовых, столбцов. Может помочь.

    4. В Постгресе сейчас есть "обёртка сторонних данных" и через неё можно стучаться, например, к mysql. К Сфинксу стучаться не пробовал, но стоит попробовать схему "данные в постгресе, полнотекстовый индекс из сфинкса подключаем через JOIN".
    Ответ написан
    Комментировать
  • Youtube data API: что за глюк с поиском видео?

    batyrmastyr
    @batyrmastyr
    Не знаю как в действительности устроен поиск в ютубе, но вот несколько возможных причин:
    1) подстрока «пе» нашлась в полном описании видео или распознанной речи, при этом там не было подстроки «пер».
    2) довольно типичное решение при полнотекстовом поиске - нормализация слов - лемматизация, стемминг, исправление опечаток и замена сокращений полными словами. Не исключено, что «пер» в их словаре оказался сокращением от «переулок», «перевод» или любого другого.
    3) исключение из поиска предлогов.
    4) исключение из поиска коротких слов, если они ни у кого не встречаются и для них нет нормальной формы.
    Ответ написан
  • Функция создания поста режит Splash?

    batyrmastyr
    @batyrmastyr
    Не экранируйте данные sql запросов самописными функциями, если не хотите получить SQL инъекцию.

    Для экранирования есть (1) mysqli::real_escape_string, (2) привязка переменных в подготовленных запросах
    $data = array_map(
        function ($value) use ($sqlConnect) { 
            return $sqlConnect->real_escape_string($value);
        },
        $registration_data
    );
    $data   = implode(',', $data);
    Ответ написан
    Комментировать
  • Api для проверки пунктуации?

    batyrmastyr
    @batyrmastyr
    online.orfo.ru - именно они в старых вордах (до 2013) и занимались проверкой правописания. Но веб-сервис они вроде как не продают, так что придётся вам покупать и подключать виндовые (или макосьные) .dll.
    Ответ написан
  • Кому реально нужны правила по использованию cookie на сайте?

    batyrmastyr
    @batyrmastyr
    В ЕС такая же история, причем длится она дольше, чем в РФ.

    Так из-за ЕС эта фигня и началась. Принимавшие этот закон чиновники, видимо, считали, что пользователи предпочтут те сайты, где за ними не следят. Получилось как всегда.
    А наши делают так либо из-за выхода на европейский рынок, либо по глупости.
    Ответ написан
    Комментировать