数仓调优|阿里资深技术专家数仓调优经验分享(下)
(一)营销业务使用场景
CREATE TABLE db.order (
order_id,
user_id,
shop_vip,
last_trade_time,
last_cart_time,
member_grade,
seller_zone,
member_credits,
clustered key index_mmsi(`user_id`)
)
DISTRIBUTED BY HASH(order_id)
PARTITION BY VALUE(DATE_FORMAT(last_trade_time, '%Y%m%d')) LIFECYCLE 30
COMMENT '订单信息表';
1.人群透视
SELECT
t2.buyer_id,
t3.seller_id,
t1.shop_vip,
t1.last_trade_time,
t1.last_cart_time,
t1.member_grade,
t1.seller_zone,
t1.member_credits,
sum(t1.pay_amount)
FROM
db.order t1
JOIN db.dimension_table1 t2 ON t1.user_id= t2.buyer_id
JOIN db.dimension_table2 t3 ON t1.user_id= t3.seller_id
WHERE
t1.is_market_target IN('4')
AND t1.seller_zone = 1019
AND t1.attributes IN('6742081')
AND t3.buyer_id = ‘xxxx’
and t3.tseller_id = ‘yyyy’
group by
t2.buyer_id,
t3.seller_id,
t1.shop_vip,
t1.last_trade_time,
t1.last_cart_time,
t1.member_grade,
t1.seller_zone,
t1.member_credits;
2.人群圈选
COUNT DISTINCT
或者GROUP BY
的操作。典型的SQL语句如下:SELECT count(1) AS cnt
FROM(
SELECT DISTINCT t1.buyer_id
FROM(
SELECT buyer_id
FROM db.order
WHERE seller_zone= 11111
AND seller_id= 121211121
AND algorithm_crowd IN('84')) t1
JOIN(
SELECT user_id AS buyer_id
FROM db.dimension_table1) t2
ON t1.buyer_id= t2.buyer_id
JOIN(
SELECT user_id AS seller_id
FROM db.dimension_table2) t3
ON t1.buyer_id= t3.seller_id
) t;
CREATE TABLE output WITH(oss_dump_endpoint= 'xxxxxx.oss-internal.aliyun-inc.com', oss_dump_bucket_name= 'xxxx',
oss_dump_file_name= 'xx_prod/20190710/63218721',
oss_dump_is_overwrite= true,
oss_dump_compatibility_mode= false,
oss_dump_access_key_id= 'xxxxxxxxx',
oss_dump_access_key_secret= 'xxxxxxxxxxxxxxxxxxxx',
oss_dump_row_del= '\r\n',
oss_dump_col_del= '\t', table_type= 'oss_dump', dump_charset_code= 'UTF-8',
oss_dump_table_header= 'false', return_dump_result_count= true) as
SELECT DISTINCT t1.buyer_id
FROM(
SELECT buyer_id
FROM db.order
WHERE last_cart_time>= 20190610
AND last_cart_time< 20190710
AND is_market_target IN('1')
AND seller_zone= 1018
AND seller_id= 3687815378) t1
JOIN(
SELECT user_id AS buyer_id
FROM db.dimension_table) t2
ON t1.buyer_id= t2.buyer_id
LIMIT 1000;
表要设置主键。主键用于排重,一旦有重复的数据写入可以直接覆盖,参考之前上篇:全网首发|阿里资深技术专家数仓调优经验分享(上)。 表要设计二级分区。一来该类数据往往量比较大,需要采用二级分区做数据的生命周期管理,自动淘汰过期的数据;二是实时写入的数据可以根据二级分区来构建索引,这样只需要增量数据构建索引,大大提高了构建索引的效率,有了索引后,数据的查询也就能快很多。 在特别大量的数据写入情况下,往往CPU的消耗也比较厉害,需要合理控制构建索引任务的并发度和时间,以避免和大流量写入峰值重合,而加重对实时写入的影响。
CREATE TABLE tb__record_info
(
a_info_id bigint NOT NULL AUTO_INCREMENT,
domain varchar NOT NULL,
region varchar NOT NULL,
ip varchar NOT NULL,
result_ts varchar NOT NULL,
time_stamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
key idx_domain(domain),
key idx_time(time_stamp),
primary key (a_info_id, domain, time_stamp)
)
DISTRIBUTE BY HASH(domain)
PARTITION BY VALUE(DATE_FORMAT(time_stamp,'%Y%m%d')) LIFECYCLE 60;
(三)游戏行业的使用场景
提供全面的游戏运营指标分析功能:全面提高游戏开发者的日常数据运营工作效率,不仅提供付费用户、付费率、付费金额和ARPU等运营指标,还强化了付费用户的留存率、回访率、用户生命周期价值等更加精细化的运营指标,游戏开发者可以更加深入,更加有效率地掌握游戏运营状态。 提供有效的渠道效果分析,使每分钱都花在刀刃上:实时的分渠道数据统计可以监测到不同渠道用户的增长、活跃、留存状况以及充值状况,更加全面、快速地分析出投资回报率,让开发者对渠道的评估更加准确。 针对付费用户追踪分析,了解付费用户的习惯:针对付费用户群,通过简单易懂的数据分析模型和图表,跟踪付费用户的留存、流失、回访和充值数据,更好地反映付费用户在整个生命周期的关键行为和价值。 细致分析玩家游戏行为,改进产品体验,提高游戏收益:关卡、道具、消费行为分析的功能可以了解道具和物品在使用过程中使用和消耗的总量以及趋势,开发者可以借此来做到恰到好处的数值平衡设计,也可充分利用数据分析的结果优化游戏内付费商品的收益。
1.活跃分析
SELECT count(DISTINCT uid) AS count
FROM login_log
WHERE timestamp >=
AND timestamp <=
AND qita1 =
AND qita2 = ;
活跃账号分析
按照日期分析,常见的DAU/WAU/MAU等 按照渠道分析,比如分包渠道或者广告渠道等
在线分析
平均在线玩家数 峰值在线玩家数
玩家行为分析
人均游戏次数,即所选日期内,总游戏次数 / 游戏人数(该数值无法完全精确统计,仅供参考) 人均游戏时长分析等
2.来源分析
SELECT Count(*) AS count FROM
(
SELECT deviceid
FROM login_log
WHERE channel_id = ‘X’
AND timestamp >= ‘XXX’
AND timestamp <= ‘YYY’
GROUP BY deviceid
) AS d1
LEFT JOIN
(
SELECT deviceid
FROM login_log
WHERE channel_id = ‘X’
AND timestamp < ‘YYY’
) AS d2
ON d1.deviceid = d2.deviceid
WHERE d1.deviceid IS NULL;
3.留存分析
SELECT
channel_id,
count(
DISTINCT IF (
datediff(payorder_riqi, login_riqi) = 0,
user_id,
NULL
)
) AS 'liucun_1',
count(
DISTINCT IF (
datediff(payorder_riqi, login_riqi) = 1,
user_id,
NULL
)
) AS 'liucun_2',
count(
DISTINCT IF (
datediff(payorder_riqi, login_riqi) = 2,
user_id,
NULL
)
) AS 'liucun_3',
count(
DISTINCT IF (
datediff(payorder_riqi, login_riqi) = 3,
user_id,
NULL
)
) AS 'liucun_4',
count(
DISTINCT IF (
datediff(payorder_riqi, login_riqi) = 4,
user_id,
NULL
)
) AS 'liucun_5',
count(
DISTINCT IF (
datediff(payorder_riqi, login_riqi) = 5,
user_id,
NULL
)
) AS 'liucun_6',
count(
DISTINCT IF (
datediff(payorder_riqi, login_riqi) = 6,
user_id,
NULL
)
) AS 'liucun_7',
count(
DISTINCT IF (
datediff(payorder_riqi, login_riqi) = 14,
user_id,
NULL
)
) AS 'liucun_15'
FROM
pay_order p
LEFT JOIN login_log l ON p.uid = l.uid
WHERE
payorder_riqi >= '2019-01-17'
AND payorder_riqi <= '2019-01-24'
GROUP BY
`channel_id`
ORDER BY
`liucun_1` DESC;
06 FAQ
SELECT (SUM(data_length)+SUM(index_length))/1024/1024/1024 AS '数据空间(GB)' FROM information_schema.tables;
用户还可以使用如下SQL语句查询当前日志占用空间:show binary logs
返回结果中的adb-bin.log表示binlog,adb-system.log表示系统日志。不同的表如果一级分区键相同,那么这些表在执行以一级分区键为Join Key的JOIN时可以大幅度减少数据Shuffle。因此在保证数据均匀的前提下,相同的一级分区键可以加速JOIN。
ALTER TABLE lineitem PARTITIONS 12
表示将lineitem的二级分区个数修改为12。需要注意的是,二级分区个数的修改是后台异步执行的,执行BUILD TABLE lineitem
可以加速分区修改任务。如果查询一定会带有某个字段,比如电商卖家透视平台的卖家id就可以作为聚集索引,保证数据的Locality,进而让性能得到量级的提升。
目前只支持一个聚集索引,但一个聚集索引可以包含多列。目前除非对非常分散的数据进行点查,否则聚集索引对性能的帮助很少。
此外需要注意的是,主键需要包含一级分区键和二级分区键。目前不支持主键的修改。
SHOW INDEX FROM tablename
。如果想要删除某个索引可以使用:ALTER TABLE tablename DROP KEY keyname
。其中keyname可以通过上面的语句查询。注意:删除索引可能会导致查询变慢。KEY key_name (column_name)
。例如:CREATE TABLE tablename (id bigint,c1 varchar,key id_idx(id)) DISTRIBUTE BY HASH(id);
。如果DDL中有主键,用主键作Distribute Key。
如果DDL中没有主键,会自动创建一个字段__adb_auto_id__
,然后使用__adb_auto_id__
作主键和分区键。
推荐阅读
点击“阅读原文”查看AnalyticDB更多信息
评论