想象一下这种情况,我有一个实体的Id,我有一个喜欢的列表,其中包含同一类的一些实体。要查找实体,何时更快在链表中执行for或在数据库中执行选择?
我的意思是,例如,当我在链表中有大约5个实体时,我想有一个for更快,而当我拥有数百万个实体时,select会更快。
但是当选择开始比for更快时?
答案 0 :(得分:5)
内存数据结构总是比打开套接字,运行查询和发回响应更快。
一个好的查询可能在10-100ms内运行,而Java操作可能需要100ns。
使用LinkedList可能无法获得最佳性能。类似于使用数据库索引,您可以改为使用HashMap,并通过其ID来映射实体:
Map<Long, Entity> idEntityMap = new HashMap<>;
idEntityMap.put(entity.getId(), entity);
因此,当您搜索实体时,只需运行:
Entity entity = idEntityMap.get(entityId);
该呼叫将首先识别实体所在的Map存储桶,并仅对该存储桶中包含的实体进行对象比较。
总而言之,内存中的操作速度非常快,但您需要使用适合您用例的数据结构。
答案 1 :(得分:1)
我机器上的1e5元素后速度更快*。 从具有一个记录槽jpa的表中进行选择的基线是1ms。
置信区间(99.9%):[0,747,1,087]
从1e5记录中选择将同时(1ms)下限增加0.1ms。
在1e5元素列表中的顺序搜索,其中所需元素最后放置2ms。
置信区间(99.9%):[2073669,347,2514442,020]
对所需元素的随机发布进行除法,将其除以2。
从1e5元素的地图中获取实体的费用将少于30ns
以下是我的同行评审基准:
EntityManagerFactory emf;
List<Individual> list;
Map<Integer, Individual> map;
@Setup
public void setUp() {
emf = Persistence.createEntityManagerFactory("postgres");
list = new ArrayList<Individual>();
map = new HashMap<Integer, Individual>();
for (int i = (int)1e5; i > 0; i--) {
Individual individual = new Individual(i);
list.add(individual);
map.put(i, individual);
}
}
@TearDown
public void tearDown() {
emf.close();
}
@Benchmark
@Fork(1)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public Individual measureJpa() {
EntityManager em = emf.createEntityManager();
Query query = em.createQuery("select i from com.company.Individual i where i.id = 1");
em.getTransaction().begin();
Individual individual = (Individual) query.getSingleResult();
em.getTransaction().commit();
em.close();
return individual;
}
@Benchmark
@Fork(1)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public Individual measureList() {
for (Individual i : list) {
if (i.id == 1) {
return i;
}
}
throw new RuntimeException();
}
@Benchmark
@Fork(1)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public Individual measureMap() {
return map.get(1);
}