我正在尝试解决我目前面临的问题。我试图找出从数据库中检索信息的最快方法。
因此传入管理员名称,我需要做的是返回所有经理被传入的用户,但如果这些用户中的任何一个恰好是经理,我必须返回所有用户名(List<String>
)他们也管理...这将重复,直到我回复所有人
这是我需要返回的一个小例子
manager --> manager --> manager --> manager --> employee
--> manager --> employee
--> manager --> manager --> manager --> employee
--> employee
所以在上面的示例中,代码将返回12个名称
我知道我可以通过多种不同的方式做到这一点,但我不知道哪种方式最好(循环递归,循环递归调用方法,SQL语句,HQL语句等等。)
由于此列表可以是任何大小,具体取决于传入的管理器,我需要找到哪个是最快的方式来检索它,因为我已经编码使用递归for循环,它需要1分20秒这是方式太久了
有什么想法吗?
答案 0 :(得分:1)
您需要执行性能分析,以了解延迟是来自数据库,应用程序服务器还是网络(由于许多循环导致的延迟)。 根据你的数据,我认为你做了太多的查询,但这是一个你应该验证的假设。
在我的公司,这是一家大公司,Big Boss与任何员工之间的关系不超过15个。因此,您不应该做超过15个请求。
我怀疑你为每个人做了一个循环,以便了解它的员工。获取manager = name的位置 您可以做的是执行一个HQL请求以将所有员工放在列表中#34;获取经理IN(经理列表)&#34;。它应该大大减少花费的时间,因为对于大老板,你会递归地执行15次请求,而不是13k。
Request 1 Request 2 Request 3 ...
manager --> manager --> manager --> manager --> employee
--> manager --> employee
--> manager --> manager --> manager --> employee
--> employee
否则,如果要使用SQL语句,可能会使用关键字WITH。
答案 1 :(得分:-1)
另请参阅Bill Karwin关于数据库反模式的this presentation。从幻灯片48开始,“天真的树”&#39;讨论反模式。
解决方案#1:路径枚举。 存储祖先的路径(管理员):
ID, PATH, NAME
1, 1/, george
2, 2/, peter
3, 1/3, harry
4, 1/3/4, bertrand
轻松查询乔治的后代:
SELECT * from Employee WHERE path LIKE '1/%';
该演示文稿还提到了我认为在您的情况下不太有用的其他解决方案:
编辑:这是将两个数据库查询与递归内存搜索混合的另一个想法。
public static class Employee {
private Long id;
private boolean isManager;
private Employee manager;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public boolean isManager() {
return isManager;
}
public void setIsManager(boolean isManager) {
this.isManager = isManager;
}
public Employee getManager() {
return manager;
}
public void setManager(Employee manager) {
this.manager = manager;
}
}
首先获取数据库中的所有管理员。如果员工总数是16k,那么管理人员的数量应该是可管理的(没有双关语)。
// gets all existing managers from the database
private static List<Employee> getAllManagers() {
// SELECT * FROM Employee WHERE isManager = true;
return new ArrayList<>();
}
然后迭代所有管理器并递归地确定哪些管理器在查询管理器下工作。
private static Set<Employee> findSubordinateManagers(Employee queryManager) {
List<Employee> allManagers = getAllManagers();
Set<Employee> subordinateManagers = new HashSet<>();
for (Employee employee : allManagers) {
if (isSubordinateTo(employee, queryManager)) {
subordinateManagers.add(employee);
}
}
return subordinateManagers;
}
// determines if the given employee is subordinate to the given manager
private static boolean isSubordinateTo(Employee employee, Employee manager) {
if (employee.getManager() == null) {
return false;
}
if (employee.getManager().getId().equals(manager.getId())) {
return true;
}
return isSubordinateTo(employee, employee.getManager());
}
然后执行第二次SQL查询以获得由所选管理器集直接管理的所有员工:
// finds all employees directly subordinate to the given set of managers
private static Set<Employee> findEmployees(Set<Employee> managers) {
// SELECT * from Employee WHERE manager IN (managers);
return new HashSet<>();
}