2012-05-12 70 views
6

假设我跟踪一个“事件”,用户需要在网站上,事件可能是一些类似:漏斗分析计算,您将如何计算漏斗?

  1. 观看网页
  2. 添加的项目到购物车
  3. 结账
  4. 支付顺序

现在,每个事件都存储在如下数据库中:

session_id EVENT_NAME CREATED_DATE ..

所以现在我想建立一个报告中显示特定的渠道,我会这样定义:

Step#1 event_n 
Step#2 event_n2 
Step#3 event_n3 

所以这个特殊的渠道有3个步骤,每个步骤与任何事件相关联。

鉴于上述数据,我该如何为此制作报告?

注意:只想清楚,我希望能够创建我定义的任何渠道,并且能够为其创建报​​告。

我能想到的最根本的方法是:

  1. 获得每一步我在我的数据库中的所有事件
  2. 步骤1将是,X%的人进行event_n
  3. 现在我将要查询的步骤#2谁也执行步骤1中的数据,并显示%
  4. 同#3但步骤3与步骤#条件2

我很好奇这些在线服务如何在托管的Saas环境中显示这些类型的报告。某种程度上,map-reduce是否使这更容易?

+0

那么你可以在减速器中获得每个会话ID的所有事件,如果你认为这使得它更容易。 –

回答

2

您对此的思考方式的核心问题是您正在考虑SQL /表类型模型。每个事件都是一个记录。 NoSQL技术的好处之一就是你可以自然地将记录存储为每个记录一个会话。一旦以基于会话的方式存储数据,就可以编写一个例程来检查会话是否符合模式。无需进行连接或任何操作,只需在会话中的事务列表上循环即可。这就是半结构化数据的力量。

如果您将会话存储在一起,该怎么办?然后,你所要做的就是遍历每个会话并查看它是否匹配。

在我看来,这是HBase的一个奇妙的用例。

使用HBase,您可以将会话ID存储为行键,然后将每个事件存储为具有时间戳作为列限定符的值。这些留给你的是按会话ID分组在一起的数据,然后按时间排序。

好吧,现在你想知道会话的百分比是什么时候执行的行为1,然后是2,然后是3.你对这些数据运行MapReduce作业。MapReduce作业将为每行键/值对提供一个会话。在数据上写一个循环来检查它是否与模式匹配。如果它计数+1,否则不。


没有全力以赴与HBase的,你可以使用MapReduce的休息时sessionize您的无组织的数据。按会话ID分组,然后在缩减器中将所有与该会话关联的事件分组在一起。现在,您基本上已经在使用HBase,您可以在Reducer中编写一个方法来检查该模式。


如果您没有可观的数据量,HBase可能会矫枉过正。任何可以分层存储数据的数据库都适用于这种情况。 MongoDB,Cassandra,Redis都浮现在脑海中,各有优缺点。

+0

不知道我是否清楚,但我想让用户能够定义渠道(每步的步骤和匹配事件),并且能够查看历史数据的报告。我想这意味着我将不得不运行批处理作业来将旧数据拖入给定的数据存储区/结构中吗?这个权利没有神奇的方式吗? – Blankman

+0

我刚刚在hbase上阅读,我喜欢如何以这种分组方式存储相关数据等。我如何做类似mongodb的事情? (hbase目前对我来说可能太多了) – Blankman

+0

是的,你必须编写某种过程才能将它们集合在一起,或者如果你正在使用存储这样的数据的数据存储,你可以修改记录。如果你在做用户,而不是会话,只需由用户分组而不是会话ID。 –

7

首先答案,使用标准的SQL,因为你的假设:

EVENTS 
----------------------------- 
SESION_ID , EVENT_NAME , TMST 

为了获得在某个时间执行步骤#1的对话:

有一个简单的布局表活动
-- QUERY 1 
SELECT SESSION_ID,MIN(TMST) FROM EVENTS WHERE EVENT_NAME='event1' GROUP BY SESSION_ID; 

这里我假设event1每个会话可能发生多次。结果是一段时间内展示event1的唯一会话列表。

为了得到第二步第三步和,我可以做相同的:

-- QUERY 2 
SELECT SESSION_ID,MIN(TMST) FROM EVENTS WHERE EVENT_NAME='event2' GROUP BY SESSION_ID; 
-- QUERY 3 
SELECT SESSION_ID,MIN(TMST) FROM EVENTS WHERE EVENT_NAME='event3' GROUP BY SESSION_ID; 

现在,你要选择进行第一步,第二步和第三步的会议 - 按照这个顺序。 更准确地说,您需要对执行步骤1的会话进行计数,然后对执行步骤2的会话进行计数,然后对执行步骤3的会话进行计数。 基本上,我们只需要3个左连接以列出进入渠道的会话结合上面的查询和步骤他们进行:

-- FUNNEL FOR S1/S2/S3 
SELECT 
    SESSION_ID, 
    Q1.TMST IS NOT NULL AS PERFORMED_STEP1, 
    Q2.TMST IS NOT NULL AS PERFORMED_STEP2, 
    Q3.TMST IS NOT NULL AS PERFORMED_STEP3 
FROM 
    -- QUERY 1 
    (SELECT SESSION_ID,MIN(TMST) FROM EVENTS WHERE EVENT_NAME='event1' GROUP BY SESSION_ID) AS Q1, 
LEFT JOIN 
    -- QUERY 2 
    (SELECT SESSION_ID,MIN(TMST) FROM EVENTS WHERE EVENT_NAME='event2' GROUP BY SESSION_ID) AS Q2, 
LEFT JOIN 
    -- QUERY 3 
    (SELECT SESSION_ID,MIN(TMST) FROM EVENTS WHERE EVENT_NAME='event2' GROUP BY SESSION_ID) AS Q3 
-- Q2 & Q3 
ON Q2.SESSION_ID=Q3.SESSION_ID AND Q2.TMST<Q3.TMST 
-- Q1 & Q2 
ON Q1.SESSION_ID=Q2.SESSION_ID AND Q1.TMST<Q2.TMST 

结果是谁在第一步进入渠道的唯一会话列表,并可能继续第二步第三步和...例如:

SESSION_ID_1,TRUE,TRUE,TRUE 
SESSION_ID_2,TRUE,TRUE,FALSE 
SESSION_ID_3,TRUE,FALSE,FALSE 
... 

现在我们只需要计算一些统计数据,例如:

SELECT 
    STEP1_COUNT, 
    STEP1_COUNT-STEP2_COUNT AS EXIT_AFTER_STEP1, 
    STEP2_COUNT*100.0/STEP1_COUNT AS PERCENTAGE_TO_STEP2, 
    STEP2_COUNT-STEP3_COUNT AS EXIT_AFTER_STEP2, 
    STEP3_COUNT*100.0/STEP2_COUNT AS PERCENTAGE_TO_STEP3, 
    STEP3_COUNT*100.0/STEP1_COUNT AS COMPLETION_RATE 
FROM 
(-- QUERY TO COUNT session at each step 
    SELECT 
    SUM(CASE WHEN PERFORMED_STEP1 THEN 1 ELSE 0 END) AS STEP1_COUNT, 
    SUM(CASE WHEN PERFORMED_STEP2 THEN 1 ELSE 0 END) AS STEP2_COUNT, 
    SUM(CASE WHEN PERFORMED_STEP3 THEN 1 ELSE 0 END) AS STEP3_COUNT 
    FROM 
    [... insert the funnel query here ...] 
) AS COMPUTE_STEPS 

等voilà!

现在进行讨论。 第一点,结果是非常简单的,因为你采取“集”(或功能)的思维方式,而不是“程序性”的方法。不要将数据库可视化为包含列和行的固定表的集合......这是如何实现的,但它不是与它进行交互的方式。这是所有的设置,你可以按照你需要的方式来安排这些设置!

第二点,如果您正在使用MPP数据库,查询将自动优化为并行运行。您甚至不需要以不同的方式编写查询,使用map-reduce或其他任何方法......我在测试数据集上运行了超过1亿次事件的相同查询,并在几秒钟内获得结果。

最后但并非最不重要的是,查询打开无限的可能性。只需根据引用者的结果,关键字,登陆页面,用户信息和分析结果进行分组,这些信息提供了最佳转换率!

+0

我认为这个查询可能有问题,例如,如果我想知道谁做了:E1,E2,E3和我有一个与E2,E1,E2,E3会话我相信上述查询将失败(因为它只考虑首次发生事件) – shaylevi2

+0

实际上并非如此。初始查询中唯一的约束是E1 E2 => E3,但这需要计数首先在会话中的事件(可以很容易地通过窗口函数完成) – SergeFantino

0

我最近发布了一个开源的蜂巢UDF做到这一点:hive-funnel-udf

这是非常简单易用这种漏斗分析的任务,你可以只写蜂巢,无需编写自定义的Java的MapReduce代码。

这只有在您使用Hive/Hadoop存储和查询数据时才有效。

+2

请不要发布[重复答案](// meta.stackexchange.com/a/211726/206345)。相反,考虑其他可以帮助未来用户找到他们需要的答案的行动,如链接文章中所述。 – Mogsdad