2017-06-14 65 views
0

我有一张表(可以称之为“操作”),列出了由一堆不同客户端完成的所有操作。寻找一种快速方法从大型数据库表中获取不同值的列表

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

我尝试了明显的100种动作类型:

SELECT DISTINCT actionType FROM actions WHERE clientId = @clientId 

但它是非常缓慢的,由于大量的表中的记录。

我现在正在使用的查询存在获得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') 

虽然我希望这是更快(希望足够快的)感觉对我来说非常hacky 有人可以建议一个更好的方法来做到这一点?

干杯, 一个

更新: 的SELECT DISTINCT正在采取昨日下午3秒,其现在立即运行!我想知道是否有人添加了索引。我会检查

由于几个人怀疑,第二个查询实际上比明显慢得多,它需要4秒钟跑!

+2

其实我认为这会慢得多,因为现在你做100个查询。 –

+2

你是否有'clientId'上的索引涵盖'actionType'? – iamdave

+0

没有集群,可能需要测试 – AidanO

回答

1

几个设计说明在这里。如果我理解正确,动作表中的动作是持续存在的。 1)如果你有一组预定义的动作类型,我的第一个建议是删除字符串,并用整数替换它们作为动作类型标识符,这将是一个查找整数值到动作类型的实际名称在一个单独的动作类型表中。然后,在动作类型标识中创建一个外键和一个非聚集索引(如果您主要对这些索引感兴趣,可以使用非空动作类型对索引进行过滤)。这样,在使用操作类型进行筛选时,您可以降低记录大小,聚集索引大小和整体性能。 2)如果你不能改变数据库设计,或者查询表的操作类型太广泛,你应该在client_id中创建一个非聚集索引,其action_type作为包含列(这也可以被过滤为非null动作类型值来缩小索引)。

+0

谢谢,非聚集索引已经在这里完成了。 – AidanO

-1

如果您在actionType上创建了一个群集索引,它应该会大大提高性能。

1

SELECT actionType FROM actions WHERE clientId = @clientId需要运行多长时间?我认为它是主要的瓶颈,而不是DISTINCT操作

看看查询计划是否确定,但是如果clientID未被索引,那么它可能是全表扫描来提取所需的数据。

一天结束时,数据库引擎将做一个散列表来获得一个独特的(就像你SELECT x FROM y GROUP BY x),这是一个需要访问所有数据的快速操作。 YOu不会以任何方式使它快速分解;速度的99%将下降到拉入数据所需的时间;作为行阅读器遍历表添加元素到一个散列表是微不足道的

+0

选择actionTypes大约需要7秒!选择不同的动作类型所需的时间不到一秒钟...... – AidanO

+1

如果您正在重复运行查询(因为它被缓存),所以始终难以真正进行性能测试。索引列和包含操作类型的建议是合理的;这意味着索引可以满足所有查询而不从表中检索行。使其更快的唯一方法是使用触发器来维护一个单独的查找表,只有在插入 –

+0

时,才会有不同的值,这个查询表不错,但如果还有其他更多的时间紧迫的问题,可能是可用的。 – AidanO

相关问题