从数据库中检索信息的最快方法

时间:2015-06-09 14:41:46

标签: java spring hibernate loops for-loop

我正在尝试解决我目前面临的问题。我试图找出从数据库中检索信息的最快方法。

因此传入管理员名称,我需要做的是返回所有经理被传入的用户,但如果这些用户中的任何一个恰好是经理,我必须返回所有用户名List<String>)他们也管理...这将重复,直到我回复所有人

这是我需要返回的一个小例子

manager --> manager --> manager --> manager --> employee
        --> manager --> employee
        --> manager --> manager --> manager --> employee
        --> employee

所以在上面的示例中,代码将返回12个名称

我知道我可以通过多种不同的方式做到这一点,但我不知道哪种方式最好(循环递归,循环递归调用方法,SQL语句,HQL语句等等。)

由于此列表可以是任何大小,具体取决于传入的管理器,我需要找到哪个是最快的方式来检索它,因为我已经编码使用递归for循环,它需要1分20秒这是方式太久了

有什么想法吗?

2 个答案:

答案 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)

请参阅this similar question

另请参阅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/%';

该演示文稿还提到了我认为在您的情况下不太有用的其他解决方案:

  • 解决方案#2:嵌套集
  • 解决方案#3:关闭表

编辑:这是将两个数据库查询与递归内存搜索混合的另一个想法。

    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<>();
    }