这就是我在PostgreSQL 10.9(public class ProductLogDaoTest {
ProductLogDao instance = new ProductLogDao();
RequestDTO requestDTO = Mockito.mock(RequestDTO.class);
JdbcTemplate jdbcTemplate = Mockito.mock(JdbcTemplate.class);
Map<String, String> requestParamMap = new HashMap<>();
@Before
public void setUp() throws Exception {
instance.setJdbcTemplate(jdbcTemplate);
}
@Test
public void getProductLogDetail_W_Custom() throws SQLException, DataAccessException {
when(requestDTO.getParameters()).thenReturn(requestParamMap);
requestParamMap.put("recordtype", "custom");
assertNotNull(instance.getProductLogDetail(requestDTO));
}
}
是x
)中所做的事情:
VARCHAR(100)
该表有超过150万条记录,并且具有索引:
SELECT COUNT(DISTINCT x) FROM t
请求耗时7秒以上。 CREATE INDEX idx_1 ON t USING btree (x)
就是这样:
EXPLAIN
怎么了?为什么不使用索引?
答案 0 :(得分:2)
这里的问题是,尽管在列t
上确实有一个B树索引,但它不一定有助于找到不同的计数。假设索引在概念上看起来像这样:
1 - 1 - 2 - 2 - 2 - 2 - 4 - 4 - 9
如果只需要最小和最大值,则可以使用理论上的索引,因为第一个和最后一个值都包含此信息,因此不需要扫描。但是,要找到所有不同的值,必须进行索引扫描。请注意,建立索引实际上并没有帮助,因为Postgres仍然必须触摸t
列中的每个值才能获得答案。
COUNT
是一个聚集函数,它倾向于索引不友好(与MIN
和MAX
可以是索引友好的)不同。
答案 1 :(得分:2)
这取决于两个因素:
无论如何,查询将必须扫描整个索引或整个表,因为PostgreSQL中没有没有索引跳过扫描 。
PostgreSQL可以扫描索引或表。
如果表最近没有被清理,则索引扫描将总是必须访问该表以确定该行是否可见。在这种情况下,顺序扫描将始终更快。
如果表最近被清理干净,并且可见性图的大多数块都标记为“全部可见”,则您可以进行仅索引扫描。 / p>
如果表的行很窄,则只进行索引扫描的可能性较小,因为那样一来,读取索引不会比读取表便宜(顺序读取会更快)。
< / li>对于具有宽行的表,您将获得仅索引扫描。