寻找一种快速方法从大型数据库表中获取不同值的列表

时间:2017-06-14 08:51:33

标签: sql sql-server query-optimization

我有一张桌子(让我们称之为'动作')列出了一堆不同客户完成的所有操作。

我想获取特定客户端的不同操作类型列表。 我也知道系统中有100种动作类型

我已经尝试过显而易见的事了:

SELECT DISTINCT actionType FROM actions WHERE clientId = @clientId

但由于表格中有大量记录,因此速度很慢。

我正在研究一个使用exists的查询来获取我怀疑会更快的actionTypes列表:

SELECT 'actionType1' WHERE EXISTS (SELECT TOP 1 * FROM actions WHERE 
   clientId = @clientID AND actionType = 'actionType1' ) 
UNION 
SELECT 'actionType2' WHERE EXISTS (SELECT TOP 1 * FROM actions WHERE 
   clientId = @clientID AND actionType = 'actionType2' ) 
UNION
.
.
.
UNION
SELECT 'actionType100' WHERE EXISTS (SELECT TOP 1 * FROM actions WHERE 
       clientId = @clientID AND actionType = 'actionType100' ) 

虽然我希望这会更快(并且希望足够快),但对我来说感觉非常恶劣 有人可以提出更好的方法吗?

干杯, 甲

更新: 选择不同昨天花了3秒,它现在立即运行!我想知道是否有人添加了索引。我会检查

正如少数人所怀疑的那样,第二个查询实际上比不同的要慢得多,它需要4秒才能运行!

3 个答案:

答案 0 :(得分:1)

这里有几个设计评论。如果我理解正确,则操作是持久存在于actions表中的字符串。

1)如果您有一组预定义的操作类型,我的第一个建议是删除字符串并将其替换为整数作为操作类型ID,这将是对操作类型的实际名称的查找整数值。一个单独的动作类型表。然后,在操作类型id中创建外键和非聚集索引(如果您对这些类型感兴趣,则可以在非null操作类型中过滤索引)。这样,当使用操作类型进行过滤时,您将降低记录大小,聚簇索引大小和整体性能。

2)如果您无法更改数据库设计或操作类型对于查找表来说过于宽泛,则应在client_id中创建非聚集索引,并将action_type作为包含列(这也可以过滤为非空操作键入值以缩小索引。)

答案 1 :(得分:1)

pos需要多长时间才能运行?我认为它是主要的瓶颈,而不是DISTINCT操作

查看查询计划以确定,但如果clientID未编入索引,则可能是全表扫描以提取所需数据。

一天结束时,数据库引擎将执行一个哈希表以获得一个独特的(与SELECT x FROM y GROUP BY x相同)以及需要访问所有数据的快速运算。你根本不会以任何方式更快地分解它; 99%的速度将降低到拉入数据所需的时间;当行阅读器遍历表时,向哈希表添加元素是微不足道的

答案 2 :(得分:-1)

如果在actionType上创建Clustered Index,它应该会大大提高性能。