Size: a a a

NodeUA - JavaScript and Node.js in Ukraine

2020 May 14

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
Якщо використовувати knex то маємо базовий запит
let baseQuery = knex.select(item.id, item_field1,item_field2,item_field3)
.from(item)
if(user && user.id) {
// додаємо умову для авторизованих
     baseQuery.modify(queryBuilder => {
       queryBuilder
         .select('bookmarks.created_at', knex.raw('CASE WHEN bookmarks.user_id IS NOT NULL THEN true ELSE false END AS is_bookmarked'))
        .leftJoin('bookmark', { 'item.id': 'bookmark.item_id' })
        .where({user_id: user.id});
     });
}
тут виходить що якщо нам не прийшов токен то ми навіть джойн не будемо робити.
якщо робити це тернарками при створенні стрінги то треба тернарками робити поля
bookmarks.created_at
is_bookmarked
LEFT JOIN bookmark ON ...
WHERE user_id =
источник

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
Кай
А з JOIN в мене була окрема історія. Свого часу в мене був такий момент, що при JOIN в кожен row додавалися дані, які могли повторюватись і при цьому загальний запит ставав дуже важким для повернення, що "не есть хорошо" і довелось прибирати JOIN і робити окремий запит для того, щоб лише унікальні поля вибирались. В подальшому нормалізував відповідь. Були окремо атрибути і поля з JOIN по типу:
{
 "attributes": [],
 "relationships": {}
}
2 запити дають подвоєну затримку.
потім ці дані треба ще і обєднати в обєкти по ід які є полями
тобто ви просто робили JOIN але вже в ноді чи в чому там
а СУБД його швидше і якісніше робить
Якщо запит йшов довго - значить він забагато даних тягнув, забули where фільтрацію. Foreign ключ не мав індексації. І далі по списку
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
Andriy Khamurda
2 запити дають подвоєну затримку.
потім ці дані треба ще і обєднати в обєкти по ід які є полями
тобто ви просто робили JOIN але вже в ноді чи в чому там
а СУБД його швидше і якісніше робить
Якщо запит йшов довго - значить він забагато даних тягнув, забули where фільтрацію. Foreign ключ не мав індексації. І далі по списку
А там не було жодної фільтрації, там були однакові значення для великої кількості елементів.
В базовому варіанті можна уявити, що на фронт передаємо список книжок, а там трапляються однакові автори. При цьому в цих авторів "дуже важкі поля" і JOIN дуже погано на цьому відбивається.
Якщо дані є - їх можна об'єднати завжди і всюди, там проблема була в тому, що якщо їх попередньо об'єднувати, то надто жирно виходить :)
источник

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
Кай
А там не було жодної фільтрації, там були однакові значення для великої кількості елементів.
В базовому варіанті можна уявити, що на фронт передаємо список книжок, а там трапляються однакові автори. При цьому в цих авторів "дуже важкі поля" і JOIN дуже погано на цьому відбивається.
Якщо дані є - їх можна об'єднати завжди і всюди, там проблема була в тому, що якщо їх попередньо об'єднувати, то надто жирно виходить :)
Нехай буде список книжок і авторів. Значить була проміжна таблиця багато до багатьох. Значить подвійний джойн. Якщо правильно проставлені індекси то це не страшно. Скоріше за все ліміт застосовувася після того як проджойнилися ці таблиці. Тобто джойнилися всі книжки на всіх авторів. Це така моя підозра.  
Переше вирішення - витягувати книжки іннер кверьою із лімітом і всіма фільтраціями. Потім на цю іннеркверю вже джойнити. І того джойнимо тільки 100 книжок на всіх потрібних авторів. Авторів по індексах підтягне швиденько. Нехай на цих 100 авторів буде 156 авторів. Тобто результуюча таблиця матиме 156 рядків. Цього можна запобігти якщо всі дані по авторах загрегувати в масив.

Друге рішення працювало швидше якраз тому що воно і симулює моє. В тому плані що не було джойну всього на все.
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
Тут загалом другий запит буде робитись виключно тоді, коли буде флаг. Так само, як where можна додавати просто через конкатенацію і без жодного query builder. В даному випадку він радше для зручності використовується, а ніж для побудови складних запитів.
Відносно моєї ситуації: З індексами і ключами все добре. Фільтрації, як такої там не було. Сама проблема була в тому, що дані важкі самі по собі.
P.S. нормалізацію можна використовувати не тільки для зберігання даних.
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
Andriy Khamurda
Нехай буде список книжок і авторів. Значить була проміжна таблиця багато до багатьох. Значить подвійний джойн. Якщо правильно проставлені індекси то це не страшно. Скоріше за все ліміт застосовувася після того як проджойнилися ці таблиці. Тобто джойнилися всі книжки на всіх авторів. Це така моя підозра.  
Переше вирішення - витягувати книжки іннер кверьою із лімітом і всіма фільтраціями. Потім на цю іннеркверю вже джойнити. І того джойнимо тільки 100 книжок на всіх потрібних авторів. Авторів по індексах підтягне швиденько. Нехай на цих 100 авторів буде 156 авторів. Тобто результуюча таблиця матиме 156 рядків. Цього можна запобігти якщо всі дані по авторах загрегувати в масив.

Друге рішення працювало швидше якраз тому що воно і симулює моє. В тому плані що не було джойну всього на все.
В такому випадку я повинен Вас засмутити. Там, скажімо так, поля з таблиці авторів видавали по кілька мегабайтів респонсу, коли як при унікальній вибірці це значення було набагато скромнішим.
Відносно вашого рішення - Вам видніше :)
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
Andriy Khamurda
Нехай буде список книжок і авторів. Значить була проміжна таблиця багато до багатьох. Значить подвійний джойн. Якщо правильно проставлені індекси то це не страшно. Скоріше за все ліміт застосовувася після того як проджойнилися ці таблиці. Тобто джойнилися всі книжки на всіх авторів. Це така моя підозра.  
Переше вирішення - витягувати книжки іннер кверьою із лімітом і всіма фільтраціями. Потім на цю іннеркверю вже джойнити. І того джойнимо тільки 100 книжок на всіх потрібних авторів. Авторів по індексах підтягне швиденько. Нехай на цих 100 авторів буде 156 авторів. Тобто результуюча таблиця матиме 156 рядків. Цього можна запобігти якщо всі дані по авторах загрегувати в масив.

Друге рішення працювало швидше якраз тому що воно і симулює моє. В тому плані що не було джойну всього на все.
Ну і відносно таблиці. Припустимо, що в книги був один автор і не було проміжної таблиці чи JOIN. Тобто в одного автора може бути багато книг, але в однієї книги лише один автор. Там в таблиці книги в полі автор був ідентифікатор автора :D
Відносно самих авторів, то вони вибиралися вже після того, як були вибрані книги і використовувався WHERE author IN (...) приводиться до звичайного =, але можна було передавати масив. Повертав це все, як написав вище. Відповідно 0 joins і кожен запит повертав чисті сутності.
источник

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
SELECT * FROM books LEFT JOIN authors ON book.author_id = author.id LIMIT 100 - це джойн 84654 книг на 156564 авторів і потім з цього монстра 100 перших рядків

SELECT * FROM (SELECT * FROM books limit 100) as books LEFT JOIN authors ON book.author_id = author.id  - це джойн 100 книг на 156564 авторів - якщо індексу по ід автора немає

SELECT * FROM (SELECT * FROM books limit 100) as books LEFT JOIN authors ON book.author_id = author.id - це джойн 100 книг на 100 авторів - якщо є індекс на ід автора у таблиці авторів

який з варіантів був одним запитом зреалізований? тому що два окремі запити це по суті третій варіант
якщо поля в таблиці авторів багато важать то вони в обох випадках мали би багато важити тому проблема була не в цьому
источник

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
EXPLAIN так би врятував в цій ситуації
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
Поля в таблиці багато важать, тому що в реальному випадку "так історично склалося".
А у випадку JOIN вони б важили ще більше, тому що якщо є 3 книги і в них один автор, то це х3. Якщо Їх було 20, то всі 20 раз поля "автора" будуть повторюватись. JOIN тут просто вбиває все.
Також часом буває так, що окремий запит працює так же швидко, як і JOIN.
От EXPLAIN і результати виконання запитів як раз і допомогти дійти до того рішення, яке було зроблене. Для Вашої ситуації це не підійшло б, моя помилка, поганий приклад.
Повертаючись до теми білдерів - все те саме пишеться ручками і при цьому результат може бути набагато кращим, якщо мова йде про складні запити.
источник

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
Тепер зрозуміло в чому була проблема. Буває.
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
В даному випадку, query builder зробив би мені веселе життя з response в стилі "по багатому", що різко негативно зобразилось би на перформансі. А якщо б це ще була ORM, то страшно уявити, як би це все конвертувалося. І при цьому, в процесі всі ці дані сидять в пам'яті, або підгружаються.
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
Головна перевага чистого SQL в таких випадках - розробник точно знає, що він пише і добитися максимального перформенсу можна лише так. У випадку JOIN, часом можна согрішити і зробити 1+1 через WHERE IN, ніхто не спонукає робити N+1. Там все буде впиратися в сам запит.
P.S. я готовий жертвувати 0.02 секунди заради того, щоб запити були простіші/"надійніші"
источник

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
Тоді ще одне питання. Що найкраще для міграцій використовувати? knex має досить хороший механізм міграцій, хоча досить очевидно що тупо привязувати міграції в БД до однієї бібліотеки node.js.
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
Забудьте, що я запитав, не так зрозумів. 😅
источник

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
Я не встиг запамятати
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
Користувався міграціями лише в Laravel, бо там вони з коробки.
За Node нічого сказати не можу :С
источник

N

Nazar in NodeUA - JavaScript and Node.js in Ukraine
Привіт. В мене таке питання. У мене  два відкритих клієнта і в кожного є список відрендерених компонентів. Вони стукаються до одного ендпоінта. Коли я видаляю на одному клієнті то запит успішний, а коли на другому то error 404 так як компонент вже видалений на сервері, а на іншому фронті він ше висить. Я думаю то треба на серваку шось фіксити. Підкажіть якесь класне рішення.
источник

V

Vitaliy in NodeUA - JavaScript and Node.js in Ukraine
Nazar
Привіт. В мене таке питання. У мене  два відкритих клієнта і в кожного є список відрендерених компонентів. Вони стукаються до одного ендпоінта. Коли я видаляю на одному клієнті то запит успішний, а коли на другому то error 404 так як компонент вже видалений на сервері, а на іншому фронті він ше висить. Я думаю то треба на серваку шось фіксити. Підкажіть якесь класне рішення.
Сервер може через вебсокети інформувати клієнтів про видалення.
источник

V

Vitaliy in NodeUA - JavaScript and Node.js in Ukraine
Або введи бізнес-помилку під це, щоб не просто 404, і на клієнті оброби правильно
источник