在不对所有记录执行循环的情况下从数据库中检索特定数据的最有效方法是啥?

Posted

技术标签:

【中文标题】在不对所有记录执行循环的情况下从数据库中检索特定数据的最有效方法是啥?【英文标题】:What is the most efficient way to retrieve specific data from DB without doing loop for all records?在不对所有记录执行循环的情况下从数据库中检索特定数据的最有效方法是什么? 【发布时间】:2018-10-15 07:46:13 【问题描述】:

我想问一下,在所有记录中不执行 for 循环的情况下,从数据库中搜索特定数据的最有效方法是什么?

我有一个关于 java spring 的项目,我有这个实体:

@Entity  
@Table(name = "USERS") public class USERS  

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "UID") 
private Integer id;

@Column(name = "FName") 
private String firstName;

@Column(name = "SName") 
private String secondName;

@Column(name = "TName") 
private String thirdName;

@Column(name = "LName") 
private String fourthName;

@Column(name = "Email") 
private String email;

@Column(name = "PW") 
private String password;

@Column(name = "MNumber") 
private String mobileNumber;

@Column(name = "ISDeleted") 
private boolean isUserDeleted;


//---------------------- Getters and Setters ----------------------

我做了这项服务:

public List<USERS> findAllActive() 
    List<USERS> usersList = new ArrayList<USERS>();
    for (USERS users: usersRepository.findAll())
        if (!users.isUserDeleted())
            usersList.add(users);
        
    
    return usersList;

例如;如果用户处于活动状态,我有一个用户属性。

所以,我的问题;什么是获取特定数据的最有效方法,例如从数据库中检索所有活动用户,而无需像上面的代码中那样执行 for 循环?因为如果用户列表是 100 万或更多,它可能会出现性能问题。

【问题讨论】:

是的,您用sql 标记了您的问题 - 现在是使用它的时候了。 “WHERE ISDeleted = false”的美妙之处,但我有点怀疑您需要一些其他过滤条件 @ScaryWombat 或者基于显示的类,可能是 JPQL。但无论哪种情况,OP 都应该对 Java 进行基本介绍,因为类和成员的命名都是非标准的。 【参考方案1】:

假设您使用的是 JpaRepository,那么您可以创建自定义查询。

@Query("SELECT u FROM USERS u WHERE u.userDeleted = false") 

List<USERS> findNotDeletedUsers();

然后拨打usersRepository.findNotDeletedUsers();

【讨论】:

【参考方案2】:

首先,在要搜索的字段上使用 index(如果该列只有两个不同的值,这对您没有多大帮助,但如果值具有高稀疏性)。

@Entity 
@Table(name = "USERS",
       indexes = 
           // not a huge performance gain, since the column values are true/false
           @Index(name = "index_by_active",  columnList="ISDeleted", unique = false),
           // possible huge performance gain, since only the relevant records are scanned        
           @Index(name = "index_by_first_name", columnList="FName", unique = false))
public class USERS ...

然后,定义一个使用索引字段的查询方法(如果您使用的是 spring 数据,它将如下所示)。

public interface UsersRepository extends CrudRepository<USERS, Long> 

    List<USERS> findUsersByISDeleted(boolean deleted);

    List<USERS> findUsersByFName(String name); 

    List<USERS> findUsersByFNameAndISDeleted(String name, boolean deleted); 


对索引字段的查询将利用基础索引并提供有效的访问计划(因此您最终不会扫描整个表来提取符合给定条件的实体子集)。

【讨论】:

【参考方案3】:

@Madis 的解决方案没问题。但是如果你总是想得到所有查询中没有被删除的用户,你可以在Entity上指定它:

@Entity 
@Table(name = "USERS")
@Where("ISDeleted = false")
public class USERS  

所以现在条件“ISDeleted = false”会自动附加到来自 UserRepository 的所有查询。您可以使用 usersRepository.findAll() 代替。

【讨论】:

【参考方案4】:

您不需要指定任何 sql 查询或 where 子句。 CrudRepository 会自动为您完成。只需使用下面的代码并根据需要传递真/假

List<Users> findIsUserDeleted(boolean isDeleted)

【讨论】:

以上是关于在不对所有记录执行循环的情况下从数据库中检索特定数据的最有效方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有 Linq 的情况下从列表中获取一些对象?

如何在没有任何循环php的情况下从数组中随机获取项目

如何在不使用 foreach 循环的情况下从视图访问模型

如何在不使用 for 循环的情况下从列表中删除元素?

如何在不使用for循环的情况下从pyspark中的列表创建数据框?

如何在触发器中循环所有列名称而不对其进行硬编码