如何计算复杂漏斗转化率

漏斗的计算

漏斗的计算归根到底是计算用户最长转化步骤的问题

  1. 漏斗一般默认是按照日期分组,所以漏斗的问题,实际上是计算用户在每日以及整个统计周期内,最长转化步骤的问题。
  2. 漏斗往往是多步的,那么就有可能在不同时间周期内完成。因此我们约定,以首事件发生的周期,作为本次漏斗转换的统计周期。(为什么不用目标事件呢,个人的理解是,首先不是每次转换都会有目标的达成,且每次转换的最长步骤可能都不一样)
  3. 漏斗的计算,每一个周期的计算都是独立的。比如 A1-A2-B的行为序列。A1 发生在1号 A2-B发生在2号。 那么1号 2号都会认为完成了A-B的转换。 这么做是为了避免统计结果会因为选择的时间范围不同而发生变化。

往往,用户的最长转换的路径不是唯一的。如果是简单漏斗,即 我只需要计算每一个步骤的转换人数。那么不唯一就是不重要的。但是,如果我希望去分析这一次转换,比如 看转换时间、分组 等等。那么就必然需要 挑选出唯一的路径。我们称之为 最优的转换的路径

最优转换的路径的规则就是规则中的:优先选择更靠近最终转化目标的事件作为转化事件,并在第一次到达目标事件时,停止继续计算


如何理解漏斗分析

漏斗的基础规则

漏斗分析是帮助运营人员分析一个多步骤过程中每一步的转化和流失情况。

假设我们在购买商品的过程,需要触发的事件包括“启动”,“登录”,“搜索商品”,“查看商品”,“生成订单”等。运营人员需要分析某段时间类(比如2020-01-01 到2020-01-07),在全部用户中依次有序触发了“登录” =》“搜索商品”=》“查看商品”=》“生成订单”事件的人群的转化流失情况,即计算全部用户中触发了“登录”事件的总人数A,A中触发了“搜索商品”事件的总人数B,B中触发了“查看商品”事件的总人数C,以及C中触发“生成订单”事件的总人数D

在进行漏斗计算时,实际情况会更加复杂,在时间范围内,用户的行为明细会出现多次包含在漏斗定义中的事件,那么会优先选择更靠近最终转化目标的事件作为转化事件,并且在第一次到达目标事件时,停止继续计算。下面的例子,转换的步骤是什么?

例1: 登陆-生成订单-搜索商品-查看商品-生成订单

例2: 登陆-搜索商品-登陆-搜索商品-搜索商品-查看商品-生成订单-生成订单

例3: 登陆-搜索商品-查看商品-生成订单-登陆-搜索商品-查看商品-生成订单


用户行为分析中的Events数据模型概述

用户行为分析基础模型的约束概述

不同于传统的BI工具,用户行为分析中的所有分析模型均是基于元数据抽象的分析模型,它底层的数据模型其实是非常简单的,即三个主体模型:用户、事件以及item,其中item只是补充作用

基础模型的特点

  1. 基于元数据来构建的
  2. 去业务的
  3. 有约束的
    1. 基于事件、用户、item模型
    2. 约定数据格式
  4. 统一用户的标识(多端的用户打通、登录前和登录后的打通)

后续的分析模型都是解决一类特定场景的问题,先定义场景,再拆解场景,最后在套用模型进行分析

主体描述:

事件:可追加,无状态的数据。用主谓宾来描述 谁在什么时候什么地点以什么方式做了一件什么事情,其5要素为:


行为分析系统的技术架构

用户行为分析技术架构

WHERE IN 子句的优化策略

WHERE IN 包含大量的元素的查询优化

应用端反馈一个涉及功能菜单渲染的基础SQL查询时间超过7秒,原因是where x in (上千个的元素),通过Presto观察,发现这个SQL的查询的时间90%花在了执行计划的解析上,真正查询时间反而很快。通过删减 where in 中的元素,发现SQL就快了很多,也证实了,问题的根本原因在in 元素集合过多


CTE:SQL with as 语法

CTE:SQL with as 语法

with as 定义

CTE 即 common table express,我们常用的 with as 短语,也叫做子查询部分(subquery factoring),主要是定义一个SQL片段,该SQL片段会被整个SQL语句所用到,也有可能在union all的不同部分,作为提供数据的部分。特别对于UNION ALL比较有用,因为union all的每一个部分可能相同,但是如果每个部分都去执行一遍的话,则成本太高,所以使用with as短语,则只要执行一遍即可。如果with as短语所定义的表名被调用两次以上,则优化器会自动将with as 短语所获取的数据放入一个temp表里。

CTE(common table express)语法

WITH Common_table_express [(column_name[,n])] AS (CTE_query_definitation)

例如:

1
2
3
with events_cte as (select event_name,event_time,ip,ua from event_table where ds==20210101)

select * from events_cte

其中cte是公用表表达式,该表达式在使用上与表变量类似,只是SQL 在处理方式上不同。


Presto执行计划 - 分发Statement到不同的QueryExecution

Presto执行计划 - 分发Statement到不同的QueryExecution

阅读源码时梳理逻辑用,无阅读价值

获取QueryExecution

queryexecution表示一次查询执行,用于启动、停止与管理一个查询,以及统计这个查询的相关信息。

在 经过Antlr 4语法解析起进行语法分析后,最终生成了一个Node,然后转成Statement,然后再包装成PreparedQuery

再看后续代码,在 dispatchQueryFactory.createDispatchQuery()方法中对不同类型的Statement 进行分发处理,其中对应的类为:QueryExecutionFactory

io.trino.dispatcher.DispatchManager.createQueryInternal()
1
2
3
4
5
6
7
8
 preparedQuery = queryPreparer.prepareQuery(session, query);
// ....
DispatchQuery dispatchQuery = dispatchQueryFactory.createDispatchQuery(
session,
query,
preparedQuery,
slug,
selectionContext.getResourceGroupId());

Presto查询计划

Presto执行计划-生成计划

阅读源码时梳理逻辑用,无阅读价值

在创建 dispatchQuery 的最后,返回了一个LocalDispatchQuery,其构造函数最后一个参数调用了 SqlQueryExecution 的start()方法


Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×