漏斗分析计算,您将如何计算漏斗?

时间:2012-05-12 19:20:23

标签: java math hadoop mapreduce bigdata

假设我跟踪用户在网站上发布的“事件”,事件可以是:

  1. 已查看主页
  2. 将商品添加到购物车
  3. 结帐
  4. 支付订单
  5. 现在,每个事件都存储在数据库中,如:

    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的条件相同
    5. 我很好奇这些在线服务如何在托管的Saas环境中显示这些类型的报告。 map-reduce是否会以某种方式使这更容易?

3 个答案:

答案 0 :(得分:7)

首先,使用标准SQL,给出您的假设: 有一个简单布局的表EVENTS:

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的唯一会话列表。

为了获得step2和step3,我可以这样做:

-- 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;

现在,您要按顺序选择执行step1,step2和step3的会话。 更准确地说,您需要计算执行步骤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

结果是在步骤1进入渠道的唯一会话列表,可能已继续执行step2和step3 ......例如:

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

Etvoilà!

现在进行讨论。 第一点,考虑到你采用“集合”(或功能)思维方式而不是“程序化”方法,结果非常简单。不要将数据库可视化为具有列和行的固定表的集合......这是它的实现方式,但它不是您与它交互的方式。这是所有套装,你可以像你需要的那样安排套装!

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

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

答案 1 :(得分:2)

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

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

在我看来,这是HBase的绝佳用例。

使用HBase,您将会话ID存储为行键,然后将每个事件存储为值,并将时间戳记作为列限定符。这给您留下的是按会话ID分组的数据,然后按时间排序。

好的,现在你要弄清楚会话的百分比是1,然后是2,然后是3.你在这个数据上运行MapReduce作业。 MapReduce作业将为您提供每行键/值对一个会话。在数据上写一个循环以检查它是否与模式匹配。如果它计数+ 1,如果不计算,则不要。


如果不完全使用HBase,您可以使用MapReduce在静止时对无组织数据进行会话。按会话ID分组,然后在reducer中,您将与该会话关联的所有事件组合在一起。现在,你基本上和HBase在一起,你可以在reducer中编写一个检查模式的方法。


如果您没有可笑的数据量,HBase可能会有点过分。在这种情况下,任何可以分层次地存储数据的数据库都会很好。 MongoDB,Cassandra,Redis都会浮现在脑海中并且有自己的优点和缺点。

答案 2 :(得分:0)

我最近发布了一个开源Hive UDF来执行此操作:hive-funnel-udf

使用这种漏斗分析任务非常简单,只需编写Hive,无需编写自定义Java MapReduce代码。

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