我有一个mysql查询,格式如下
dslContext
.select(
ITEMDATA.ITEMID,
ITEMDATA.COST,
ITEMNAMES.ITEMNAME
)
.from(ITEMDATA)
.join(ITEMNAMES)
.on(ITEMDATA.ITEMID=ITEMNAMES.ITEMID)
.where(conditions);
上述查询将ITEMDATA与ITEMNAMES表连接,以在结果中选择ITEMNAME。我在内存中缓存ITEMNAMES表,并希望避免与ITEMNAMES表的连接。这将加速查询并简化查询,因为实际查询要复杂得多。
我想用它类似于以下内容。我想在select params列表中调用itemNamesCache.getItemName,它给出ITEMNAME并返回select结果的一部分。 getItemName
应将响应中返回的ITEMID作为参数,并提供ITEMNAME。
dslContext.
select(
ITEMDATA.ITEMID,
ITEMDATA.COST,
itemNamesCache.getItemName(valueOfItemId)
)
.from(ITEMDATA)
.where(conditions);
P.S:我可以迭代结果并调用itemNamesCache.getItemName。但是如果可能的话,我想使用查询中嵌入的东西
答案 0 :(得分:1)
您无法从SQL查询回调到某些Java逻辑,即使您使用jOOQ(以及Java)构建SQL查询这一事实使得它看起来可行。
但是,您可以使用以前构建的缓存修补记录来后处理jOOQ结果:
如果你正在使用一个真正无法处理这个简单连接的数据库(并且你已经检查过你有所有正确的索引和约束!)那么你可以尝试以下解决方案:
// Assuming this import:
import static org.jooq.impl.DSL.*;
...写
Map<Integer, String> itemNamesCache =
dslContext.selectDistinct(ITEMNAMES.ITEMID, ITEMNAMES.NAME)
.from(ITEMNAMES)
.fetchMap(ITEMNAMES.ITEMID, ITEMNAMES.NAME);
dslContext
.select(
ITEMDATA.ITEMID,
ITEMDATA.COST,
// create an empty column here
inline(null, String.class).as(ITEMNAMES.NAME))
.from(ITEMDATA)
.where(conditions)
// fill the empty column with cached values
.fetch(r -> r.value3(itemNamesCache.get(r.value1())));
SQL的方法是编写correlated subquery。
SELECT
itemdata.itemid,
itemdata.cost,
(SELECT itemnames.name FROM itemnames WHERE itemnames.itemid = itemdata.itemid)
FROM
itemdata
WHERE
...
// Assuming this import:
import static org.jooq.impl.DSL.*;
...写道:
dslContext
.select(
ITEMDATA.ITEMID,
ITEMDATA.COST,
field(select(ITEMNAMES.NAME)
.from(ITEMNAMES)
.where(ITEMDATA.ITEMID.eq(ITEMNAMES.ITEMID)))
.as(ITEMNAMES.NAME)
)
.from(ITEMDATA)
.where(conditions)
.fetch();
理论上,两个查询应该以完全相同的速度运行,因为它们是等效的(如果ITEMDATA.ITEMID
上有外键)。
实际上,大多数数据库可能会有更好的JOIN
查询性能,除非它们实现标量子查询缓存(例如Oracle),这可以大大加快第二个查询,具体取决于distinct {的数量{ {1}}(越小越好)。