Forwarded from Kirill Polikarpov
Наткнулся в Книге Том Кайта "ORACLE для профессионалов" на то, что автор использует вьюхи v$mystat, v$statname для анализа запросов.
Написал свой вариант, который можно запускать в любом IDE.
Получилась мини трассировка.
SQL
Написал свой вариант, который можно запускать в любом IDE.
Получилась мини трассировка.
SQL
DECLARE
TYPE trStats IS RECORD
(
consistentGets INT,
physicalReads INT,
physicalWrites INT,
redoSize INT,
recursiveCalls INT,
pgaMemoryMax INT,
openedCursors INT
);
old_stats_data trStats;
new_stats_data trStats;
row_count INTEGER;
docId NUMBER := 453;
PROCEDURE get_current_stats (stats_data OUT trStats) IS
stats trStats;
BEGIN
SELECT s.cr,
s.pr,
s.pw,
s.redo_size,
s.recursive_calls,
s.pga_max_memory,
s.opened_cursors
INTO stats.consistentGets,
stats.physicalReads,
stats.physicalWrites,
stats.redoSize,
stats.recursiveCalls,
stats.pgaMemoryMax,
stats.openedCursors
FROM (SELECT sn.name, ms.VALUE AS stat_value
FROM v$mystat ms, v$statname sn
WHERE ms.statistic# = sn.statistic#)
PIVOT (MAX (stat_value)
FOR name
IN ('consistent gets' AS cr,
'physical reads' AS pr,
'physical writes' AS pw,
'recursive calls' AS recursive_calls,
'redo size' AS redo_size,
'session pga memory max' AS pga_max_memory,
'opened cursors current' AS opened_cursors)) s;
stats_data := stats;
END get_current_stats;
PROCEDURE stats_diff2str (old_stats_data IN trStats, new_stats_data IN trStats) IS
stats_diff_str VARCHAR2 (4000);
BEGIN
stats_diff_str :=
CASE
WHEN old_stats_data.consistentGets - new_stats_data.consistentGets IS NOT NULL THEN
SUBSTR (
'consistent gets: '
|| TO_CHAR (old_stats_data.consistentGets - new_stats_data.consistentGets)
|| ', physical reads: '
|| TO_CHAR (old_stats_data.physicalReads - new_stats_data.physicalReads)
|| ', physical writes: '
|| TO_CHAR (old_stats_data.physicalWrites - new_stats_data.physicalWrites)
|| ', recursive calls: '
|| TO_CHAR (old_stats_data.redoSize - new_stats_data.redoSize)
|| ', redo size: '
|| TO_CHAR (old_stats_data.recursiveCalls - new_stats_data.recursiveCalls)
|| ', session pga memory max: '
|| TO_CHAR (old_stats_data.pgaMemoryMax - new_stats_data.pgaMemoryMax)
|| ', opened cursors current: '
|| TO_CHAR (old_stats_data.openedCursors),
1,
200)
END;
DBMS_OUTPUT.put_line (stats_diff_str);
END stats_diff2str;
BEGIN
get_current_stats (stats_data => old_stats_data);
SELECT 1 INTO row_count FROM DUAL;
get_current_stats (stats_data => new_stats_data);
stats_diff2str (old_stats_data => old_stats_data, new_stats_data => new_stats_data);
END;
👍1👎1
Допустим, есть задача: на вход метода приходит коллекция типа TABLE и данные коллекции требуется вставить в таблицу.
Anonymous Poll
0%
FOR, а потом INSERT по каждому
61%
FORALL + INSERT
28%
Преобразую в запросе коллекцию командой TABLE, а потом один INSERT для всех строкам сразу
17%
Не морочьте мне голову
👍1👎1
mass_insert_table.sql
5.8 KB
Мои исследования темы вставки и обновления таблицы по заданной коллекцией показали, что однозначно команда FORALL быстрее.
#Cases
#Cases
👍1👎1
Задача от начальника разработки DB большого знатока Postgres - Ивана Петровича Могилы.
"Она такая, из практики, поэтому не очень красивая. Я нашим бдшникам её давал. Но она очень завязана на особенности postgresql"
Опишите логику, что делает эта функция
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#PostgreSQL#PL/pgSQL
💼 #RealInterviewTasks
"Она такая, из практики, поэтому не очень красивая. Я нашим бдшникам её давал. Но она очень завязана на особенности postgresql"
Опишите логику, что делает эта функция
CREATE OR REPLACE FUNCTION dba_tools.pgcompact_clean_pages(_table_ident text, _column_ident text, _to_page integer, _page_offset integer, _max_tupples_per_page integer) RETURNS integer
LANGUAGE plpgsql
AS $_$
DECLARE
_from_page integer := _to_page - _page_offset + 1;
_min_ctid tid;
_max_ctid tid;
_ctid_list tid[];
_next_ctid_list tid[];
_ctid tid;
_loop integer;
_result_page integer;
_update_query text :=
'UPDATE ONLY ' || _table_ident ||
' SET ' || _column_ident || ' = ' || _column_ident ||
' WHERE ctid = ANY($1) RETURNING ctid';
BEGIN
-- Check page argument values
IF NOT (
_page_offset IS NOT NULL AND _page_offset >= 1 AND
_to_page IS NOT NULL AND _to_page >= 1 AND
_to_page >= _page_offset)
THEN
RAISE EXCEPTION 'Wrong page arguments specified.';
END IF;
-- Check that session_replication_role is set to replica to
-- prevent triggers firing
IF NOT (
SELECT setting = 'replica'
FROM pg_catalog.pg_settings
WHERE name = 'session_replication_role')
THEN
RAISE EXCEPTION 'The session_replication_role must be set to replica.';
END IF;
-- Define minimal and maximal ctid values of the range
_min_ctid := (_from_page, 1)::text::tid;
_max_ctid := (_to_page, _max_tupples_per_page)::text::tid;
-- Build a list of possible ctid values of the range
SELECT array_agg((pi, ti)::text::tid)
INTO _ctid_list
FROM generate_series(_from_page, _to_page) AS pi
CROSS JOIN generate_series(1, _max_tupples_per_page) AS ti;
<<_outer_loop>>
FOR _loop IN 1.._max_tupples_per_page LOOP
_next_ctid_list := array[]::tid[];
-- Update all the tuples in the range
FOR _ctid IN EXECUTE _update_query USING _ctid_list
LOOP
IF _ctid > _max_ctid THEN
_result_page := -1;
EXIT _outer_loop;
ELSIF _ctid >= _min_ctid THEN
-- The tuple is still in the range, more updates are needed
_next_ctid_list := _next_ctid_list || _ctid;
END IF;
END LOOP;
_ctid_list := _next_ctid_list;
-- Finish processing if there are no tupples in the range left
IF coalesce(array_length(_ctid_list, 1), 0) = 0 THEN
_result_page := _from_page - 1;
EXIT _outer_loop;
END IF;
END LOOP;
-- No result
IF _loop = _max_tupples_per_page AND _result_page IS NULL THEN
RAISE EXCEPTION
'Maximal loops count has been reached with no result.';
END IF;
RETURN _result_page;
END$_$;
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#PostgreSQL#PL/pgSQL
💼 #RealInterviewTasks
👍1👎1
DB developers channel
Задача от начальника разработки DB большого знатока Postgres - Ивана Петровича Могилы. "Она такая, из практики, поэтому не очень красивая. Я нашим бдшникам её давал. Но она очень завязана на особенности postgresql" Опишите логику, что делает эта функция CREATE…
Логика функции следующая:
1. Идем по записям определенного диапазона страниц таблицы (далее Х),
для этого нам нужен только ctid, он доступен всем кто имеет права на чтение таблицы
2. Для каждой записи делаем update, создается новая версия строки,
эта версия может быть как в том же диапазоне Х, так и выше или ниже
- Если новая версия строки оказалась в странице выше диапазона Х,
то выходим, поэтому диапазон лучше указывать из хвоста таблицы, чтобы такая ситуация была невозможна
- Если новая версия строки оказалась в том же диапазоне Х, то делаем update снова
- Если новая версия строки оказалась в странице ниже диапазона Х,
то идем дальше, старую версию потом удалит vacuum
Таким образом с помощью update мы пытаемся согнать все строки из указанного диапазона страниц в страницы ниже,
а этот диапазон освободить. Если он будет в хвосте таблицы, то vacuum сможет его освободить полностью.
У vacuum в postgres есть особенность, что он освобождает место занятое таблицей только с конца
т.е. полностью пустые странице в хвосте могут быть освобождены,
но пустые страницы в середине не могут, если за ними есть страницы с живыми строками.
Ну и ещё одна особенность.
Тут returning вернет ctid новой версии строки, так что значение будет отличаться от того, что передано в параметре.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💼 #RealInterviewTasks
1. Идем по записям определенного диапазона страниц таблицы (далее Х),
для этого нам нужен только ctid, он доступен всем кто имеет права на чтение таблицы
2. Для каждой записи делаем update, создается новая версия строки,
эта версия может быть как в том же диапазоне Х, так и выше или ниже
- Если новая версия строки оказалась в странице выше диапазона Х,
то выходим, поэтому диапазон лучше указывать из хвоста таблицы, чтобы такая ситуация была невозможна
- Если новая версия строки оказалась в том же диапазоне Х, то делаем update снова
- Если новая версия строки оказалась в странице ниже диапазона Х,
то идем дальше, старую версию потом удалит vacuum
Таким образом с помощью update мы пытаемся согнать все строки из указанного диапазона страниц в страницы ниже,
а этот диапазон освободить. Если он будет в хвосте таблицы, то vacuum сможет его освободить полностью.
У vacuum в postgres есть особенность, что он освобождает место занятое таблицей только с конца
т.е. полностью пустые странице в хвосте могут быть освобождены,
но пустые страницы в середине не могут, если за ними есть страницы с живыми строками.
Ну и ещё одна особенность.
UPDATE ONLY t_table_ident SET
id = id
WHERE ctid = ANY($1)
RETURNING ctid;
Тут returning вернет ctid новой версии строки, так что значение будет отличаться от того, что передано в параметре.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💼 #RealInterviewTasks
👎1
Простая, но интересная задача на понимание.
(Мне задавали на собесе в 2022 году)
Необходимо написать запрос, который позволит понять, идентичны ли данные в двух таблицах.
Порядок хранения данных в таблицах значения не имеет.
Пример данных:
T1:
a b
1 1
2 2
2 2
3 3
4 4
T2:
a b
1 1
2 2
3 3
3 3
4 4
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💼 #RealInterviewTasks #SQL
(Мне задавали на собесе в 2022 году)
Необходимо написать запрос, который позволит понять, идентичны ли данные в двух таблицах.
Порядок хранения данных в таблицах значения не имеет.
create table t1(a number, b number);
create table t2(a number, b number);
Пример данных:
T1:
a b
1 1
2 2
2 2
3 3
4 4
T2:
a b
1 1
2 2
3 3
3 3
4 4
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💼 #RealInterviewTasks #SQL
❤2👎1
DB developers channel
Простая, но интересная задача на понимание. (Мне задавали на собесе в 2022 году) Необходимо написать запрос, который позволит понять, идентичны ли данные в двух таблицах. Порядок хранения данных в таблицах значения не имеет. create table t1(a number, b number);…
Решение задачи вариант 1:
На собесе я решил через FULL OUTER JOIN
На текущий момент добавил все красивости и мое решение выглядело бы так:
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💼 #RealInterviewTasks #SQL
На собесе я решил через FULL OUTER JOIN
На текущий момент добавил все красивости и мое решение выглядело бы так:
SELECT CASE
WHEN EXISTS
(SELECT NULL
FROM (SELECT STANDARD_HASH (TO_CHAR (t1.a) || '/' || TO_CHAR (t1.b), 'MD5') AS hash_row, COUNT (*) AS row_amount
FROM t1
GROUP BY STANDARD_HASH (TO_CHAR (t1.a) || '/' || TO_CHAR (t1.b), 'MD5')) t11
FULL OUTER JOIN
(SELECT STANDARD_HASH (TO_CHAR (t2.a) || '/' || TO_CHAR (t2.b), 'MD5') AS hash_row, COUNT (*) AS row_amount
FROM t2
GROUP BY STANDARD_HASH (TO_CHAR (t2.a) || '/' || TO_CHAR (t2.b), 'MD5')) t21
ON (t11.hash_row = t21.hash_row AND t11.row_amount = t21.row_amount)
WHERE t11.hash_row IS NULL OR t21.hash_row IS NULL) THEN
'DIFFERENT'
ELSE
'IDENTICAL'
END AS comparison_result
FROM DUAL;
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💼 #RealInterviewTasks #SQL
❤1👎1
DB developers channel
Простая, но интересная задача на понимание. (Мне задавали на собесе в 2022 году) Необходимо написать запрос, который позволит понять, идентичны ли данные в двух таблицах. Порядок хранения данных в таблицах значения не имеет. create table t1(a number, b number);…
Кстати, чат GPT предложил решение через MINUS.
Я слегка его переделал и
и это решение мне тоже нравится
Вариант 2
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💼 #RealInterviewTasks #SQL
SELECT CASE
WHEN
(
SELECT COUNT(*) FROM (
SELECT a, b, COUNT(*) cnt FROM t1 GROUP BY a, b
MINUS
SELECT a, b, COUNT(*) cnt FROM t2 GROUP BY a, b
)
) = 0
AND
(
SELECT COUNT(*) FROM (
SELECT a, b, COUNT(*) cnt FROM t2 GROUP BY a, b
MINUS
SELECT a, b, COUNT(*) cnt FROM t1 GROUP BY a, b
)
) = 0
THEN 'IDENTICAL'
ELSE 'DIFFERENT'
END AS comparison_result
FROM dual;
Я слегка его переделал и
и это решение мне тоже нравится
Вариант 2
SELECT CASE
WHEN
EXISTS
(
SELECT STANDARD_HASH (TO_CHAR (t1.a) || '/' || TO_CHAR (t1.b), 'MD5') AS hash_row, COUNT (*) AS row_amount
FROM t1
GROUP BY STANDARD_HASH (TO_CHAR (t1.a) || '/' || TO_CHAR (t1.b), 'MD5')
MINUS
SELECT STANDARD_HASH (TO_CHAR (t2.a) || '/' || TO_CHAR (t2.b), 'MD5') AS hash_row, COUNT (*) AS row_amount
FROM t2
GROUP BY STANDARD_HASH (TO_CHAR (t2.a) || '/' || TO_CHAR (t2.b), 'MD5')
)
OR
EXISTS
(
SELECT STANDARD_HASH (TO_CHAR (t2.a) || '/' || TO_CHAR (t2.b), 'MD5') AS hash_row, COUNT (*) AS row_amount
FROM t2
GROUP BY STANDARD_HASH (TO_CHAR (t2.a) || '/' || TO_CHAR (t2.b), 'MD5')
MINUS
SELECT STANDARD_HASH (TO_CHAR (t1.a) || '/' || TO_CHAR (t1.b), 'MD5') AS hash_row, COUNT (*) AS row_amount
FROM t1
GROUP BY STANDARD_HASH (TO_CHAR (t1.a) || '/' || TO_CHAR (t1.b), 'MD5')
)
THEN 'DIFFERENT'
ELSE 'IDENTICAL'
END AS comparison_result
FROM dual;
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
💼 #RealInterviewTasks #SQL
👎1
В книге Дж. Льюиса "Oracle. Основы стоимостной оптимизации" в Главе I на 7 странице на 20 строчке сказано "Приведи друга разработчика на канал и будет тебе удача на неделю. Приведи 3 друзей и будет тебе счастье на месяц". Мысль спорная. Как вы считаете?
Anonymous Poll
50%
Согласен
8%
Не согласен
42%
Не пудрите мне мозги!!! Дж. Льюис не тот автор, на которого стоит ориентироваться
👎1
🔎 Сложная задача с собеса в компанию UNLIMIT
(Я её не решил в моменте т.е. как не решил, я предложил вариант, но он ресурсный и потому неподходящий.)
Задача на уровень Senior, а может быть Expert.
💡 Условие:
У нас — высоконагруженная база ORACLE:
📈 до 1000 и выше транзакций в секунду.
Часть из них — commit, часть — rollback.
Нужно:
📆 Назначать каждой транзакции уникальный порядковый номер в пределах суток (часа, минуты)
При этом:
🔁 Номера должны идти без пропусков и дублей.
📌 Сохраняем их в таблице transactions.
⛔ Нельзя использовать блокировки, которые мешают другим транзакциям.
⚡ Назначение номера должно происходить быстро.
📊 Пример:
Дата Номер транзакции
01.01.2025 1
01.01.2025 2
... ...
01.01.2025 1000009
02.01.2025 1
02.01.2025 2
... ...
🤔 Как бы вы реализовали такой счётчик?
С условиями:
Без блокировок
Без пробелов
Быстро
И чтобы не сносило систему под нагрузкой
Пишите ваши идеи 👇
🔄 UPDATE 02.02.2025:
Спасибо, что с нами есть Иван Петрович.
📌 В PostgreSQL такое провернуть невозможно.
Дело в том, что PostgreSQL при попытке вставки уникального значения блокирует строку (если используется, например, SELECT ... FOR UPDATE, INSERT ... ON CONFLICT, уникальные индексы и т. д.).
Сессии, которые вставляют те же значения одновременно, вынуждены ждать — из-за row-level locks.
🔄 UPDATE 23.09.2025:
Спасибо, что с нами есть Евгений Артурович.
💡 В Oracle поведение аналогичное - при вставке двух новых значений в уникальный индекс ошибка проявляется в момент коммита. Поэтому для избежание конкуренции назначения номера должно быть в автономной транзакции.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#RealInterviewTasks #Oracle #PL/SQL
(Я её не решил в моменте т.е. как не решил, я предложил вариант, но он ресурсный и потому неподходящий.)
Задача на уровень Senior, а может быть Expert.
💡 Условие:
У нас — высоконагруженная база ORACLE:
📈 до 1000 и выше транзакций в секунду.
Часть из них — commit, часть — rollback.
Нужно:
📆 Назначать каждой транзакции уникальный порядковый номер в пределах суток (часа, минуты)
При этом:
🔁 Номера должны идти без пропусков и дублей.
📌 Сохраняем их в таблице transactions.
⛔ Нельзя использовать блокировки, которые мешают другим транзакциям.
⚡ Назначение номера должно происходить быстро.
📊 Пример:
Дата Номер транзакции
01.01.2025 1
01.01.2025 2
... ...
01.01.2025 1000009
02.01.2025 1
02.01.2025 2
... ...
🤔 Как бы вы реализовали такой счётчик?
С условиями:
Без блокировок
Без пробелов
Быстро
И чтобы не сносило систему под нагрузкой
Пишите ваши идеи 👇
🔄 UPDATE 02.02.2025:
Спасибо, что с нами есть Иван Петрович.
📌 В PostgreSQL такое провернуть невозможно.
Дело в том, что PostgreSQL при попытке вставки уникального значения блокирует строку (если используется, например, SELECT ... FOR UPDATE, INSERT ... ON CONFLICT, уникальные индексы и т. д.).
Сессии, которые вставляют те же значения одновременно, вынуждены ждать — из-за row-level locks.
🔄 UPDATE 23.09.2025:
Спасибо, что с нами есть Евгений Артурович.
💡 В Oracle поведение аналогичное - при вставке двух новых значений в уникальный индекс ошибка проявляется в момент коммита. Поэтому для избежание конкуренции назначения номера должно быть в автономной транзакции.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#RealInterviewTasks #Oracle #PL/SQL
👎1
💡 Разбор «невозможной» задачи про сквозной счётчик-без-пробелов
🔑 Главные наблюдения
INSERT — самая быстрая DML-операция; читаем как можно меньше.
FAST FULL INDEX SCAN даёт O(1) чтение «хвоста» уникального индекса.
Сессии изолированы, но автономная транзакция и уникальный индекс гарантирует, что два одинаковых значения не вставятся одновременно.
🛠 Алгоритм
Шаг Действие Почему это безопасно
1 Читаем последний номер через SELECT … ORDER BY num DESC FETCH 1
(FAST FULL INDEX SCAN) Один блочный I/O, без блокировок
2 INSERT INTO period_tx_idx(period, num) VALUES(:p, :last_num) Дешевле, чем update
3 Если вставка успешна → номер наш ✅ Уникальный индекс не дал коллизии
4 Если ORA-00001 / unique constraint → кто-то уже взял этот num → num := num + 1 и GO TO 2 Перебираем до победы — обычно 1-2 попытки
🔸 На практике при 1 000 TPS конкурируют считанные сессии → конфликт мизерный.
🔸 «Дырки» возможны только при аварийном выключении питания в момент вставки, и то чисто теоретически.
❗️ Практический совет
Такой счетчик надо организовывать после всей логики и всех проверок, все констрейны на уровне таблицы тоже должны быть дополнительно проверены, чтобы избежать неожиданного EXCEPTION.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#RealInterviewTasks #Oracle #PL/SQL
🔑 Главные наблюдения
INSERT — самая быстрая DML-операция; читаем как можно меньше.
FAST FULL INDEX SCAN даёт O(1) чтение «хвоста» уникального индекса.
Сессии изолированы, но автономная транзакция и уникальный индекс гарантирует, что два одинаковых значения не вставятся одновременно.
🛠 Алгоритм
Шаг Действие Почему это безопасно
1 Читаем последний номер через SELECT … ORDER BY num DESC FETCH 1
(FAST FULL INDEX SCAN) Один блочный I/O, без блокировок
2 INSERT INTO period_tx_idx(period, num) VALUES(:p, :last_num) Дешевле, чем update
3 Если вставка успешна → номер наш ✅ Уникальный индекс не дал коллизии
4 Если ORA-00001 / unique constraint → кто-то уже взял этот num → num := num + 1 и GO TO 2 Перебираем до победы — обычно 1-2 попытки
🔸 На практике при 1 000 TPS конкурируют считанные сессии → конфликт мизерный.
🔸 «Дырки» возможны только при аварийном выключении питания в момент вставки, и то чисто теоретически.
❗️ Практический совет
Такой счетчик надо организовывать после всей логики и всех проверок, все констрейны на уровне таблицы тоже должны быть дополнительно проверены, чтобы избежать неожиданного EXCEPTION.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#RealInterviewTasks #Oracle #PL/SQL
❤2👎1
period_transaction_index.sql
2.8 KB
Скрипт для проверки. Можно запустить в разных сессиях и посмотреть.
UPDATE 23.09.2025 Указанный скрипт неточный.
Исправленный скрипт в комментариях.
UPDATE 23.09.2025 Указанный скрипт неточный.
Исправленный скрипт в комментариях.
👋 Друзья, хочу сделать контент полезнее для вас. Подскажите, что вам интереснее всего читать в канале? 🧠 Формат, о котором идёт речь — короткие задачки, фичи, кейсы из реальных проектов. Проголосуйте ниже 👇 📊 Что тебе интереснее всего?
Anonymous Poll
20%
Простые задачи с собесов (Junior–Middle)
53%
Сложные задачи с реальных интервью (Senior+)
27%
Сферические кони в вакууме надоели - давай приёмы, грабли и фичи из реальной практики (бой и прод)
👎1
🎵 "Вы хотите песен? Их есть у меня."
— С. Шнуров
Сегодня — не песня, а задачка на размышление (из собеса с одной иностранной компанией). На первый взгляд — идентичные конструкции, но за ними скрыта важная разница.
Сравните два варианта:
a)
b)
📌 Вопрос:
В чём концептуальная разница между этими двумя подходами?
Ясно, что написано криво, но это специально.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
Обсудим в комментариях 👇
(а позже добавлю разбор)
#RealInterviewTasks #sql #Oracle #PostgreSQL #PL/SQL #PL/pgSQL
— С. Шнуров
Сегодня — не песня, а задачка на размышление (из собеса с одной иностранной компанией). На первый взгляд — идентичные конструкции, но за ними скрыта важная разница.
Сравните два варианта:
a)
SELECT *
FROM table1 t1
WHERE (SELECT t2.column2
FROM table2 t2
WHERE t2.id = t1.id) = t1.column1;
b)
CREATE OR REPLACE FUNCTION f1(id NUMBER) RETURN VARCHAR2 IS
x table2.column2%TYPE;
BEGIN
SELECT t.column2
INTO x
FROM table2 t
WHERE t.id = f1.id;
RETURN x;
END f1;
/
SELECT *
FROM table1 t1
WHERE f1(t1.id) = t1.column1;
📌 Вопрос:
В чём концептуальная разница между этими двумя подходами?
Ясно, что написано криво, но это специально.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
Обсудим в комментариях 👇
(а позже добавлю разбор)
#RealInterviewTasks #sql #Oracle #PostgreSQL #PL/SQL #PL/pgSQL
❤2👎1🤔1
"Пусть я переору любого соловья..."
— Шнур
Недавний случай из практики.
Java-разработчики обращаются к БД, как умеют — через IN (...) :
<select id="select" resultType="Long">
SELECT order_id
FROM table_1
WHERE order_id IN
<foreach item="orderId" collection="orderIds" separator="," open="(" close=")">
#{orderId}
</foreach>
</select>
На выходе в логах базы — десятки разных SQL-запросов:
SELECT order_id FROM table_1 WHERE order_id IN (:1)
SELECT order_id FROM table_1 WHERE order_id IN (:1, :2, :3)
...
SELECT order_id FROM table_1 WHERE order_id IN (:1, ..., :999)
Вроде всё работает. Но вот вопрос:
❓ Корректно ли так обращаться к базе?
Если нет — почему, и как бы вы это исправили?
💬 Делитесь опытом и решениями — интересно, кто как решает такие "мелочи", которые под нагрузкой превращаются в проблему.
⚠️ Хотите проверить скрипты, но нет базы под рукой - онлайн-песочница
💎 Поддержка канала⁉️
#Cases #sql #Oracle #PostgreSQL #PL/SQL #PL/pgSQL
👎1😱1
