我根本不是SQL的专业人士:) 有一个非常关键的性能问题。 以下是与问题直接相关的信息。
我的数据库表condos
和表goods
中有2个表。
表condos
包含字段:
表项目:
我在condos
表中有1000多个实体,在items
表中有1000多个实体。
问题是我如何执行项目搜索
目前是:
例如,我想获取city = Sydney
SELECT condos.condo_id FROM public.condos WHERE city = 'Sydney'
SELECT * FROM public.items WHERE item.condo_id = ?
制作一个condo_id
。问题是,一旦我在condos
表中获得了1000多个实体,则每个condo_id
属于“悉尼”的请求执行1000次以上。并且执行此请求需要花费大约2分钟,这是一个关键的性能问题。
所以,问题是:
我执行此类搜索的最佳方式是什么?我应该在单WHERE
个请求中添加1000+ id吗?或?
对于添加信息,我使用 PostgreSQL 9.4 和 Spring MVC 。
答案 0 :(得分:2)
使用表join
执行查询,这样您就不需要执行其他查询。在您的情况下,您可以通过condos
加入items
和condo_id
,例如:
SELECT i.*
FROM public.items i join public.condos c on i.condo_id = c.condo_id
WHERE c.city = 'Sydney'
请注意,性能调优是一个主题。它可以因环境而异,取决于您如何构建表中的数据以及如何组织代码中的数据。
以下是其他一些可能也有帮助的建议:
尝试将索引添加到您使用排序和搜索的字段,例如city
中的condos
和condo_id
中的items
。有一个很好的answer来解释索引的工作原理。
我还建议您执行EXPLAIN
为您的查询设计查询计划是否存在可能导致性能问题的全表搜索。
希望这可以提供帮助。
答案 1 :(得分:1)
基本上你需要的是消除N + 1查询,同时确保你的城市字段被编入索引。你有3种机制可以去。在您收到的其他一个答案中已经说明了一个是SUBSELECT方法。除了这种方法,你还有两个。
您可以使用您所声明的内容:
SELECT condos.condo_id FROM public.condos WHERE city = 'Sydney'
SELECT *
FROM public.items
WHERE items.condo_id IN (up to 1000 ids here)
我之前提到1000的原因是因为某些SQL提供商有限制。
您也可以通过联接来消除N + 1选择
SELECT *
FROM public.items join public.condos on items.condo_id=condos.condo_id and condos.city='Sydney'
现在3个查询之间有什么区别。
Subselect查询的优点是您一次获得所有内容。 缺点是,如果你有太多的元素,性能可能会受到影响:
简单的优点条款。有效地解决了N + 1问题, 与Subselect
相比,缺点可能导致一些额外的查询加入查询专家,您可以一次性初始化公寓和项目。 缺点导致公寓方面的一些数据重复
如果我们看一下像Hibernate这样的框架,我们可以发现在大多数情况下,使用获取策略或者加入IN策略。很少使用子选择。
此外,如果您有关键性能,您可以考虑阅读内存中的所有内容并从那里提供服务。从这两个表的内容来看,将其上传到Map中应该相当容易。
如果我们只讨论1000次查询,那么解决您的N + 1查询问题的所有内容都是您的解决方案。所有这三个选项都是解决方案。
答案 2 :(得分:0)
您可以在第二个查询中将第一个查询用作in
运算符中的子查询:
SELECT *
FROM public.items
WHERE item.condo_id IN (SELECT condos.condo_id
FROM public.condos
WHERE city = 'Sydney')