Предположим, у меня есть следующая структура таблицы:
create table PEOPLE (
ID integer not null primary key,
NAME varchar(100) not null
);
create table CHILDREN (
ID integer not null primary key,
PARENT_ID_1 integer not null references PERSON (id),
PARENT_ID_2 integer not null references PERSON (id)
);
и я хочу создать список имен каждого человека, который является родителем.В пятно я могу написать что-то вроде:
for {
parent <- people
child <- children if {
parent.id === child.parent_id_1 ||
parent.id === child.parent_id_2
}
} yield {
parent.name
}
, и это генерирует ожидаемый SQL:
select p.name
from people p, children c
where p.id = c.parent_id_1 or p.id = c.parent_id_2
Однако это не является оптимальным: часть выражения OR
может вызватьужасно низкая производительность в некоторых СУБД, которые заканчивают тем, что выполняют полные таблицы, чтобы присоединиться к p.id
, даже если там есть индекс (см., например, этот отчет об ошибках для H2 ).Общая проблема заключается в том, что планировщик запросов не может знать, быстрее ли выполнить каждую сторону OR
по отдельности и объединить результаты вместе или просто выполнить полное сканирование таблицы [2].
IХотелось бы генерировать SQL, который выглядит примерно так, который затем может использовать индекс (первичный ключ), как и ожидалось:
select p.name
from people p, children c
where p.id in (c.parent_id_1, c.parent_id_2)
Мой вопрос: как я могу сделать это впятно?Существующие методы, кажется, не предлагают пути:
ColumnExtensionMethods.in
принимает Query
в качестве параметра, но у меня нет Query
У меня есть номер или Rep[Long]
для каждого из моих столбцов идентификаторов
ColumnExtensionMethods.inSet
для привязки существующих (известных) литеральных массивов, а не для присоединения кнаборы столбцов
Я хотел бы написать что-то вроде этого:
for {
parent <- people
child <- children
if parent.id in (child.parent_id_1, child.parent_id_2)
} yield {
p.name
}
, но сейчас это невозможно.
[1] Мой настоящий дизайн немного сложнее, чем этот, но он сводится к той же проблеме.
[2] Некоторые СУБД do имеют эту оптимизацию для простых случаев,например, ИЛИ-расширение в Oracle .