PgSQL · 应用案例 · 手机行业分析、决策系统设计-实时圈选、透视、估算

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介:

背景

经营分析、决策支持是现代企业的一个让数据发挥有效价值的分析型系统。

在各个行业中随处可见,例如共享充电宝中,协助销售了解实时的设备租赁情况,销售业绩。在电商中,协助小二和商户发掘目标用户群体。金融行业中,协助输出国民的存款、消费、贷款的画像。

PostgreSQL, Greenplum都是非常适合于经营分析、决策支持的数据库。因为它们具备了一些特性,适合实时的分析透视。(流式计算、合并写入、阅后即焚、GIN倒排索引、varbit类型、列存储、BITMAP合并扫描、HLL估值类型、采样算法等等)。

我也写过很多实际的应用案例,可以参考本文末尾。

经营分析系统的需求大同小异,在手机行业中,以imei或imsi为KEY,每个手机根据它的用户的行为,生成一些属性,针对每个属性,划分出不同的标签,形成了手机用户的画像。再针对画像进行人群的圈选、透视,协助分析。

例如,基于PostgreSQL数组以及GIN索引的设计:

1

经营分析设计示例

1、目标设计

2、表结构设计

3、属性表

4、标签表

5、标签表索引设计

6、打标签(含新增、更新、删除标签)测试

7、圈选测试

8、透视测试

9、决策设计示例

流式+函数式计算

结构设计

1、手机用户属性表

create table tbl1 (  
  imei text primary key,     -- 手机唯一标识  
  v1 int,        -- 年龄  
  v2 float8,     -- 收入  
  v3 geometry,   -- 住址经纬  
  v4 geometry,   -- 公司经纬  
  v5 char(1),    -- 性别  
  v6 timestamp,  -- 最后活跃时间  
  v7 int2,       -- 每日在线时长  
  v8 int2,       -- 星座  
  v9 text,       -- 其他标签。。。。。  
  ......  
);

2、标签元数据表

create table tbl2 (  
  tagid int primary key,    -- 标签名  
  desc text,    -- 描述,例如性别,年龄分段,收入分段,区域等等,作为一个标签标识。  
);

3、标签表

create table tbl3 (  
  imei text primary key,   -- 手机唯一标识  
  tagids int[],            -- 标签数组  
  ins_tags int[],          -- 合并操作需要的中间字段  
  del_tags int[]           -- 合并操作需要的中间字段  
);  
  
create index idx_tbl3_tagids on tbl3 using gin (tagids gin__int_ops);  
或
create index idx_tbl3_tagids on tbl3 using gist (tagids gist__intbig_ops);  
或
create index idx_tbl3_tagids on tbl3 using gist (tagids gist__int_ops);

4、标签表与属性表实际上可以合一,在透视时,可以避免一次JOIN(降低透视的耗时),但是会引入更新IO放大的问题,因为属性表可能是宽表。

根据实际的性能情况来选择是否合一。

需求与SQL设计

1、圈人

select imei from tbl3 where tagids @> array[标签1, 标签2];  -- 查找包含标签1,标签2的人群。  
  
select imei from tbl3 where tagids && array[标签1, 标签2];  -- 查找包含标签1,标签2中任意一个或多个的人群。  
  
select imei from tbl3 where tagids && array[标签1, 标签2] and tagid @> array[标签3, 标签4];  -- 查找包含标签3,标签4。同时包含标签1,标签2中任意一个或多个的人群。

2、针对圈出人群的精准透视

select v8,count(*) from tbl1 where  
  imei = any (array(  
                     select imei from tbl3 where tagids @> array[标签1, 标签2]  
             )     )  
group by v8;

3、新增或追加标签

使用intarray插件,简化数组交、并、差操作。

create extension intarray;  
insert into tbl3 (imei, tagids) values (?, ?[]) on conflict (imei) do update set tagids=tbl3.tagids|excluded.tagids;

4、删标签

update tbl3 set tagids = tagids - ?[] where imei=?;

5、更新标签

update tbl3 set tagids = ?[] where imei=?;

6、批量并行新增、追加、删除、更新标签优化

如果要一次性操作很多条记录(例如1000万条记录),并且有并行的贴标签操作(同一条用户被多个SQL更新)。需要注意两个问题:

6.1 大事务导致膨胀的问题,建议分段操作。

6.2 行锁冲突问题,建议新增(插入),然后合并到标签表。

优化方法,

实现标签最终一致性。

将直接增、删、改标签表,改成写行为日志tag_log,采用任务调度,批量合并到标签表:

create table tag_log (  
  imei text,    -- 手机唯一标识  
  action text,  -- insert, delete  表示增加、删除标签  (更新需求应该没有,如有,直接到标签表操作)  
  tagids int[], -- 标签IDs  
  crt_time timestamp default clock_timestamp()   -- 时间  
);  
  
create index idx_tag_log_1 on tag_log (crt_time);  
  
-- 16个分区表
do language plpgsql 
$$

declare
begin
  for i in 0..15 loop
    execute format('create table tag_log%s (like tag_log including all) inherits(tag_log)', i);
  end loop;
end;

$$
;
串行任务,阅后即焚(假设-99999999是一个永远不存在的TAGID)

-- CTE语法,支持阅后即焚的批量合并方法
with tmp as (delete from tag_log where ctid = any ( array (
select ctid from tag_log order by crt_time limit 10000 -- 按时序,批量取1万条
)) returning * )
, tmp1 as (select imei,

         uniq(sort(array_agg(case when action='insert' then tagids else -99999999 end))) - (-99999999) AS ins_tags,  
         uniq(sort(array_agg(case when action='delete' then tagids else -99999999 end))) - (-99999999) AS del_tags  
       from (select imei, action, unnest(tagids) as tagids from tmp) t group by imei)  

insert into tbl3 (imei, tagids, ins_tags, del_tags)
select imei, ins_tags-del_tags, ins_tags, del_tags from tmp1
on conflict (imei) do update set tagids=((tbl3.tagids | excluded.ins_tags) - excluded.del_tags), ins_tags=excluded.ins_tags, del_tags=excluded.del_tags;

并行任务,阅后即焚

例如开启16个并行  
  
abs(mod(hashtext(imei), 16))=?
-- CTE语法,支持阅后即焚的批量合并方法  
with tmp as (delete from tag_log where ctid = any ( array (  
  select ctid from tag_log where abs(mod(hashtext(imei), 16))=0 order by crt_time limit 10000  -- 按时序,批量取1万条,按HASH并行  
  )) returning * )  
, tmp1 as (select imei,  
             uniq(sort(array_agg(case when action='insert' then tagids else -99999999 end))) - (-99999999) AS ins_tags,  
             uniq(sort(array_agg(case when action='delete' then tagids else -99999999 end))) - (-99999999) AS del_tags  
           from (select imei, action, unnest(tagids) as tagids from tmp) t group by imei)  
insert into tbl3 (imei, tagids, ins_tags, del_tags)  
select imei, ins_tags-del_tags, ins_tags, del_tags from tmp1  
 on conflict (imei) do update set tagids=((tbl3.tagids | excluded.ins_tags) - excluded.del_tags), ins_tags=excluded.ins_tags, del_tags=excluded.del_tags;  
写成函数,方便调用

create or replace function consume_tag_log(mo int, mov int, lim int) returns void as 
$$
  
declare  
begin  
  execute format($_$with tmp as (delete from tag_log where ctid = any ( array (  
  select ctid from tag_log where abs(mod(hashtext(imei), %s))=%s order by crt_time limit %s  
  )) returning * )  
, tmp1 as (select imei,  
             uniq(sort(array_agg(case when action='insert' then tagids else -99999999 end))) - (-99999999) AS ins_tags,  
             uniq(sort(array_agg(case when action='delete' then tagids else -99999999 end))) - (-99999999) AS del_tags  
           from (select imei, action, unnest(tagids) as tagids from tmp) t group by imei)  
insert into tbl3 (imei, tagids, ins_tags, del_tags)  
select imei, ins_tags-del_tags, ins_tags, del_tags from tmp1  
 on conflict (imei) do update set tagids=((tbl3.tagids | excluded.ins_tags) - excluded.del_tags), ins_tags=excluded.ins_tags, del_tags=excluded.del_tags$_$,  
 mo, mov, lim);  
end;  

$$
 language plpgsql strict;  
  
  
select consume_tag_log(16,0,10000);   -- 并行处理  
select consume_tag_log(16,1,10000);  
.....  
select consume_tag_log(16,15,10000);  
create or replace function consume_tag_log(lim int) returns void as 
$$
  
declare  
begin  
  execute format($_$with tmp as (delete from tag_log where ctid = any ( array (  
  select ctid from tag_log order by crt_time limit %s  
  )) returning * )  
, tmp1 as (select imei,  
             uniq(sort(array_agg(case when action='insert' then tagids else -99999999 end))) - (-99999999) AS ins_tags,  
             uniq(sort(array_agg(case when action='delete' then tagids else -99999999 end))) - (-99999999) AS del_tags  
           from (select imei, action, unnest(tagids) as tagids from tmp) t group by imei)  
insert into tbl3 (imei, tagids, ins_tags, del_tags)  
select imei, ins_tags-del_tags, ins_tags, del_tags from tmp1  
 on conflict (imei) do update set tagids=((tbl3.tagids | excluded.ins_tags) - excluded.del_tags), ins_tags=excluded.ins_tags, del_tags=excluded.del_tags$_$,  
 lim);  
end;  

$$
 language plpgsql strict;  
  
  
select consume_tag_log(10000);  -- 每次处理1万条  
创建调度任务,执行消费函数调度即可。

阅后即焚的处理速度,每秒 百万行。

《(OLTP) 高吞吐数据进出(堆存、行扫、无需索引) - 阅后即焚(读写大吞吐并测)》

性能验证
1、标签取值范围5万,正态分布

2


2、多表批量写入函数
create or replace function ins(
  imei text,
  tagids int[]
) returns void as 
$$

declare
  suffix int := abs(mod(hashtext(imei),16)); 
begin
  execute format($_$insert into tag_log%s values ('%s', 'insert', '%s'::int[])$_$, suffix, imei, tagids);
end;

$$
 language plpgsql strict;

3、多表批量消费

标签表分表

do language plpgsql 
$$

declare
begin
  for i in 0..15 loop
    execute format('create table tbl3_%s (like tbl3 including all) inherits(tbl3)', i);
  end loop;
end;

$$
;

多表批量消费

CREATE OR REPLACE FUNCTION public.consume_tag_log(suffix int, lim integer)
 RETURNS void
 LANGUAGE plpgsql
 STRICT
AS $function$
declare
begin
  execute format($_$with tmp as (delete from tag_log%s where ctid = any ( array (  
  select ctid from tag_log%s order by crt_time limit %s  -- 按时序,批量取1万条,按HASH并行
  )) returning * )   
, tmp1 as (select imei, 
             uniq(sort(array_agg(case when action='insert' then tagids else -99999999 end))) - (-99999999) AS ins_tags,   
     uniq(sort(array_agg(case when action='delete' then tagids else -99999999 end))) - (-99999999) AS del_tags
   from (select imei, action, unnest(tagids) as tagids from tmp) t group by imei)  
insert into tbl3_%s (imei, tagids, ins_tags, del_tags) 
select imei, ins_tags-del_tags, ins_tags, del_tags from tmp1 
 on conflict (imei) do update set tagids=((tbl3_%s.tagids | excluded.ins_tags) - excluded.del_tags), ins_tags=excluded.ins_tags, del_tags=excluded.del_tags$_$,
 suffix, suffix, lim, suffix, suffix);
end;
$function$;

4、数据写入压测脚本

vi test.sql  
  
\set tag1 random_gaussian(1, 50000, 20)  
\set tag2 random_gaussian(1, 50000, 20)  
\set tag3 random_gaussian(1, 50000, 20)  
\set tag4 random_gaussian(1, 50000, 20)  
\set tag5 random_gaussian(1, 50000, 20)  
\set tag6 random_gaussian(1, 50000, 20)  
\set tag7 random_gaussian(1, 50000, 20)  
\set tag8 random_gaussian(1, 50000, 20)  
\set imei random(1,1000000000)  
select ins(:imei, (array[:tag1,:tag2,:tag3,:tag4,:tag5,:tag6,:tag7,:tag8])::int[]);
  
nohup pgbench -M prepared -n -r -P 1 -f ./test.sql -c 28 -j 28 -T 3000 >./tag.log 2>&1 &

5、数据消费,并行调度

用秒杀技术实现并行调度,避免单个HASH被重复调用。

《HTAP数据库 PostgreSQL 场景与性能测试之 30 - (OLTP) 秒杀 - 高并发单点更新》

这里直接用分区表写入的话,性能会更爽,原理请看如下:

《阿里云RDS PostgreSQL OSS 外部表 - (dblink异步调用封装)并行写提速案例》

vi test1.sql  
  
\set mov random(0,15)  
select consume_tag_log(:mov,10000) where pg_try_advisory_xact_lock(:mov);  
  
nohup pgbench -M prepared -n -r -P 1 -f ./test1.sql -c 16 -j 16 -T 3000 >./consume.log 2>&1 &

6、压测结果

写入速度

单条单步写入,约 14.3万 行/s  
  
改成多表批量写入,可以提高到100万+ 行/s

消费速度

单表并行批量消费,约 25.5万 行/s  
  
改成多表并行批量消费,可以提高到 100万+ 行/s

查询速度,毫秒级

postgres=# explain (analyze,verbose,timing,costs,buffers) select count(imei) from tbl3 where tagids @> (array[25281,25288])::int[];
                                                           QUERY PLAN                                                           
--------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=224.50..224.51 rows=1 width=8) (actual time=2.745..2.746 rows=1 loops=1)
   Output: count(imei)
   Buffers: shared hit=193
   ->  Bitmap Heap Scan on public.tbl3  (cost=218.44..224.49 rows=5 width=33) (actual time=2.716..2.738 rows=9 loops=1)
         Output: imei, tagids, ins_tags, del_tags
         Recheck Cond: (tbl3.tagids @> '{25281,25288}'::integer[])
         Heap Blocks: exact=9
         Buffers: shared hit=193
         ->  Bitmap Index Scan on idx_tbl3_tagids  (cost=0.00..218.44 rows=5 width=0) (actual time=2.707..2.707 rows=9 loops=1)
               Index Cond: (tbl3.tagids @> '{25281,25288}'::integer[])
               Buffers: shared hit=184
 Planning time: 0.165 ms
 Execution time: 2.797 ms
(13 rows)

除了以上基于数组、GIN索引的设计,PostgreSQL还有一些技术,可以用在经营分析系统。

技术1 实时透视 - 技术之 - 流式统计

通过insert on conflict,流式的统计固定模型的维度数据。

《PostgreSQL 流式统计 - insert on conflict 实现 流式 UV(distinct), min, max, avg, sum, count …》

满足这类查询的实时流式统计:

select a,count(*),sum(b),avg(b),min(b),max(b) from tbl group by a;

技术2 实时透视、估算 - 技术之 - 流式统计 + HLL

通过insert on conflict,流式的统计固定模型的维度数据。这里要用到hll插件,存储count(dinstinct x)的估值

《PostgreSQL 流式统计 - insert on conflict 实现 流式 UV(distinct), min, max, avg, sum, count …》

《PostgreSQL hll (HyperLogLog) extension for “State of The Art Cardinality Estimation Algorithm” - 3》

《PostgreSQL hll (HyperLogLog) extension for “State of The Art Cardinality Estimation Algorithm” - 2》

《PostgreSQL hll (HyperLogLog) extension for “State of The Art Cardinality Estimation Algorithm” - 1》

满足这类查询的实时流式统计:

select a, count(distinct b) from tbl group by a;

技术3 实时透视、估算 - 技术之 - 计划估算

根据执行计划得到评估行。

《妙用explain Plan Rows快速估算行》

如果输入多个字段条件,为了提高行估算准确度,可以定义多字段统计信息,10新增的功能:

《PostgreSQL 10 黑科技 - 自定义统计信息》

满足这类查询的估算需求:

select count(*) from tbl where xxxx;  
  
SQL换算成  
  
select * from tbl where xxxx; -- 通过explain的行估算拿结果

技术4 实时透视、估算 - 技术之 - 采样估算

《秒级任意维度分析1TB级大表 - 通过采样估值满足高效TOP N等统计分析需求》

采样估算,适合求TOP N。

满足这类查询的估算需求:

select a from tbl group by a order by count(*) desc limit N;

技术5 实时圈选、透视 - 技术之 - GIN倒排

倒排索引针对多值类型,例如 hstore, array, tsvector, json, jsonb。

主树的K-V分别为:

element-ctid(行号)list or tree

辅树为

ctid list or tree

从而高效的满足这类查询的需求:

-- 包含哪些元素  
select * from tbl where arr @> array[xx,xx];  
  
-- 包含哪些任意元素之一  
select * from tbl where arr && array[xx,xx];

内部使用BITMAP扫描方法,过滤到少量数据块。

《PostgreSQL 9种索引的原理和应用场景》

技术6 实时圈选、透视 - 技术之 - bitmap

这个方法非常的巧妙,将tag和imei做了倒转,以tag为key, imei为bitmap来存储。

create table tag_users (  
  tagid int primary key, -- 标签  
  imeibitmap varbit,     -- 每个imei用一个BIT位表示  
);

查询换算:

-- 包含某些标签的用户  
select bitand(imeibitmap) from tag_users where tagid in (?,?,...);  
  
-- 包含任意标签的用户  
select bitor(imeibitmap) from tag_users where tagid in (?,?,...);

案例参考:

《阿里云RDS for PostgreSQL varbitx插件与实时画像应用场景介绍》

《基于 阿里云 RDS PostgreSQL 打造实时用户画像推荐系统(varbitx)》

技术7 实时圈选、透视 - 技术之 - 并行计算

PostgreSQL 10加入了并行计算的能力,在join , filter, seqscan, order by, agg, group等方面都支持并行。

性能指标参考:

《HTAP数据库 PostgreSQL 场景与性能测试之 23 - (OLAP) 并行计算》

技术8 实时圈选、透视 - 技术之 - MPP, 列存储, 位图索引

基于PostgreSQL的MPP 数据仓库Greenplum,支持列存储,位图索引。

用资源,暴力解决问题。

没有太多的设计技巧,堆机器就可以,但是本身的效率远比impalar, hive好很多。

Greenplum是非常值得推荐的OLAP数据库。在金融、政府、航空等大数据领域有众多案例。

决策支持技术

流式数据处理+UDF函数计算技术。可以满足实时决策的需求。

案例如下:

《HTAP数据库 PostgreSQL 场景与性能测试之 32 - (OLTP) 高吞吐数据进出(堆存、行扫、无需索引) - 阅后即焚(JSON + 函数流式计算)》

《HTAP数据库 PostgreSQL 场景与性能测试之 27 - (OLTP) 物联网 - FEED日志, 流式处理 与 阅后即焚 (CTE)》

相似案例举例

1、实时统计 count(distinct)估值,min, max, avg, sum, count精确值。

《PostgreSQL 流式统计 - insert on conflict 实现 流式 UV(distinct), min, max, avg, sum, count …》

2、

《PostgreSQL 异步消息实践 - Feed系统实时监测与响应(如 电商主动服务) - 分钟级到毫秒级的实现》

《(OLTP) 物联网 - FEED日志, 流式处理 与 阅后即焚 (CTE)》

3、让explain产生精确的多字段输入条件行数估值(select * from table where a=? and|or b=? ....)

《PostgreSQL 10 黑科技 - 自定义统计信息》

4、《恭迎万亿级营销(圈人)潇洒的迈入毫秒时代 - 万亿user_tags级实时推荐系统数据库设计》

《阿里云RDS for PostgreSQL varbitx插件与实时画像应用场景介绍》

《基于 阿里云 RDS PostgreSQL 打造实时用户画像推荐系统(varbitx)》

5、决策支持,流式函数计算

《(OLTP) 高吞吐数据进出(堆存、行扫、无需索引) - 阅后即焚(JSON + 函数流式计算)》

《(OLTP) 高吞吐数据进出(堆存、行扫、无需索引) - 阅后即焚(读写大吞吐并测)》

6、圈人案例

《(OLAP) 用户画像圈人场景 - 数组相交查询与聚合》

《(OLAP) 用户画像圈人场景 - 数组包含查询与聚合》

7、时间、空间、多维圈人、透视案例

《空间|时间|对象 圈人 + 透视 - 暨PostgreSQL 10与Greenplum的对比和选择》

《PostgreSQLGPDB 毫秒级海量 时空数据透视 典型案例分享》

《PostgreSQLGPDB 毫秒级海量 多维数据透视 案例分享》

8、视频网站透视案例

《音视图(泛内容)网站透视分析 DB设计 - 阿里云(RDS、HybridDB) for PostgreSQL最佳实践》

9、

《画像圈人 + 人群行为透视》

《奔跑吧,大屏 - 时间+空间 实时四维数据透视》

《数据透视 - 商场(如沃尔玛)选址应用》

《海量用户实时定位和圈人 - 团圆社会公益系统(位置寻人圈人)》

《万亿级电商广告 - brin黑科技带你(最低成本)玩转毫秒级圈人(视觉挖掘姊妹篇) - 阿里云RDS PostgreSQL, HybridDB for PostgreSQL最佳实践》

《多字段,任意组合条件查询(无需建模) - 毫秒级实时圈人 最佳实践》

10、

《经营、销售分析系统DB设计之PostgreSQL, Greenplum - 共享充电宝 案例实践》

相关实践学习
AnalyticDB MySQL海量数据秒级分析体验
快速上手AnalyticDB MySQL,玩转SQL开发等功能!本教程介绍如何在AnalyticDB MySQL中,一键加载内置数据集,并基于自动生成的查询脚本,运行复杂查询语句,秒级生成查询结果。
阿里云云原生数据仓库AnalyticDB MySQL版 使用教程
云原生数据仓库AnalyticDB MySQL版是一种支持高并发低延时查询的新一代云原生数据仓库,高度兼容MySQL协议以及SQL:92、SQL:99、SQL:2003标准,可以对海量数据进行即时的多维分析透视和业务探索,快速构建企业云上数据仓库。 了解产品 https://www.aliyun.com/product/ApsaraDB/ads
相关文章
|
11月前
|
Android开发 开发者 UED
个人开发 App 成功上架手机应用市场的关键步骤
个人开发 App 成功上架手机应用市场的关键步骤
|
11月前
|
运维 监控 开发工具
应用研发平台EMAS产品常见问题之华为手机没收到通知如何解决
应用研发平台EMAS(Enterprise Mobile Application Service)是阿里云提供的一个全栈移动应用开发平台,集成了应用开发、测试、部署、监控和运营服务;本合集旨在总结EMAS产品在应用开发和运维过程中的常见问题及解决方案,助力开发者和企业高效解决技术难题,加速移动应用的上线和稳定运行。
|
11月前
|
安全 Java 数据库连接
【Java每日一题】——第四十四题:综合案例:编程模拟智能手机和普通手机功能。
【Java每日一题】——第四十四题:综合案例:编程模拟智能手机和普通手机功能。
|
3月前
|
人工智能 算法 前端开发
OmAgent:轻松构建在终端设备上运行的 AI 应用,赋能手机、穿戴设备、摄像头等多种设备
OmAgent 是 Om AI 与浙江大学联合开源的多模态语言代理框架,支持多设备连接、高效模型集成,助力开发者快速构建复杂的多模态代理应用。
396 72
OmAgent:轻松构建在终端设备上运行的 AI 应用,赋能手机、穿戴设备、摄像头等多种设备
|
2月前
|
机器学习/深度学习 存储 人工智能
MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
MNN-LLM App 是阿里巴巴基于 MNN-LLM 框架开发的 Android 应用,支持多模态交互、多种主流模型选择、离线运行及性能优化。
2223 20
MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
|
6月前
|
数据采集 数据挖掘 UED
电商平台手机销售数据采集与分析
随着科技的进步,尤其是手机的普及,国民生活变得更加便捷。现今,手机销售已从传统的实体店模式转向电商平台,这一转变加剧了市场竞争,给手机厂商带来了新的挑战。为了应对挑战,电商平台越来越重视手机销售情况与用户体验,利用数据分析成为了解市场趋势的关键手段。本章节聚焦于某电商平台的手机销售及售后数据收集,通过深入分析商品销售状况与用户反馈,旨在探索有效的营销策略,助力电商平台与手机行业的共同进步。
198 1
|
3月前
|
XML 人工智能 文字识别
Mobile-Agent:通过视觉感知实现自动化手机操作,支持多应用跨平台
Mobile-Agent 是一款基于多模态大语言模型的智能代理,能够通过视觉感知自主完成复杂的移动设备操作任务,支持跨应用操作和纯视觉解决方案。
896 10
Mobile-Agent:通过视觉感知实现自动化手机操作,支持多应用跨平台
|
5月前
|
Web App开发 定位技术 iOS开发
Playwright 是一个强大的工具,用于在各种浏览器上测试应用,并模拟真实设备如手机和平板。通过配置 `playwright.devices`,可以轻松模拟不同设备的用户代理、屏幕尺寸、视口等特性。此外,Playwright 还支持模拟地理位置、区域设置、时区、权限(如通知)和配色方案,使测试更加全面和真实。例如,可以在配置文件中设置全局的区域设置和时区,然后在特定测试中进行覆盖。同时,还可以动态更改地理位置和媒体类型,以适应不同的测试需求。
Playwright 是一个强大的工具,用于在各种浏览器上测试应用,并模拟真实设备如手机和平板。通过配置 `playwright.devices`,可以轻松模拟不同设备的用户代理、屏幕尺寸、视口等特性。此外,Playwright 还支持模拟地理位置、区域设置、时区、权限(如通知)和配色方案,使测试更加全面和真实。例如,可以在配置文件中设置全局的区域设置和时区,然后在特定测试中进行覆盖。同时,还可以动态更改地理位置和媒体类型,以适应不同的测试需求。
399 1
|
6月前
|
Web App开发 缓存 前端开发
拿下奇怪的前端报错(六):多摄手机webrtc拉取视频流会导致应用崩溃,从而无法进行人像扫描
本文介绍了一种解决手机摄像头切换导致应用崩溃的问题的方法。针对不支持facingMode配置的四摄手机,通过缓存和序号切换的方式,确保应用在特定设备上不会频繁崩溃,提升用户体验。
181 1
|
6月前
|
SQL 存储 数据可视化
手机短信SQL分析技巧与方法
在手机短信应用中,SQL分析扮演着至关重要的角色

热门文章

最新文章

  • 1
    阿里云无影云手机怎么用?非常简单,云手机创建、价格及连接使用图文教程
    67
  • 2
    什么是阿里云无影云手机?看完秒懂,云手机价格、创建及连接教程
    97
  • 3
    TaoAvatar:手机拍出电影级虚拟人!阿里3D高斯黑科技让动捕设备下岗
    171
  • 4
    SpatialLM:手机视频秒建3D场景!开源空间认知模型颠覆机器人训练
    118
  • 5
    算法系统协同优化,vivo与港中文推出BlueLM-V-3B,手机秒变多模态AI专家
    68
  • 6
    【02】整体试验思路,在这之前我们发现sec_uid,sec_uid是什么和uid的关系又是什么?相互如何转换?python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
    117
  • 7
    【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
    78
  • 8
    【01】整体试验思路,如何在有UID的情况下获得用户手机号信息,python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
    281
  • 9
    美团面试:手机扫描PC二维码登录,底层原理和完整流程是什么?
    192
  • 10
    MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
    2223