用sparkR, 分析上億條訂單數據的腳本。

来源:http://www.cnblogs.com/realzjx/archive/2016/07/28/5716309.html
-Advertisement-
Play Games

上周我們這個10人的小團隊開發的推薦拉新系統, 日拉新人數已接近4萬人。過去幾個月這個系統從無到有, 拉新從日增幾千穩步增長到日增幾萬, 同事們幾個月來,每天工作13個小時以上,洗澡時間都沒有, 有時就住在公司, 回家怕吵到家人,只能睡客廳地板, 周日也不能保證休息。 大家的全力投入,不懈努力才能有 ...


上周我們這個10人的小團隊開發的推薦拉新系統, 日拉新人數已接近4萬人。過去幾個月這個系統從無到有, 拉新從日增幾千穩步增長到日增幾萬, 同事們幾個月來,每天工作13個小時以上,洗澡時間都沒有, 有時就住在公司, 回家怕吵到家人,只能睡客廳地板, 周日也不能保證休息。 大家的全力投入,不懈努力才能有這個結果。 非常感慨團隊產生的的化學反應, 和驚人的生產效率。 產品穩定後,最近全面轉入大數據分析, 和機器學習階段, 開始做真正的增長黑客實踐。 spark, R, scala都是剛剛開始深入地學習,沒幾天, 還好有數據, 學的快!, 不休息, 連做夢都是在做分析數據的工作, 日進千里啊。 

剛開始用spark-sql的時候, 如果做一個複雜的查詢,寫一長串sql, 誰都看不懂,拆成小sql, 就要保存中間結果, 效率低下。 用了幾天後, 開始切入sparkR和Scala , 發現效率比直接用spark-sql高太多了, 代碼可讀性也強太多。此外善用cahe,也可以有效提高效率。

下麵都是乾貨。廢話不多少, 只希望幫到你。

工作目標: 分析一下新手券分享的拉新效果和人數,需要對最近15日的訂單大概2億多條訂單紀錄, 以及300萬左右的領券紀錄, 幾十萬筆的返利信息做全庫查詢 , 這在msql上是不可能完成的任務。 對spark+hive來說, 也很耗時, 但一個小時內可以搞定。

用R寫了一下查詢腳本, 稍後準備改成scala的。 兩者都是調用spark api, 區別應該只在語法上。 

用15個節點的spark跑這個查詢腳本, 大概需要半個多小時才能出來結果。代碼是最完整,最準確的文檔, 提綱挈領的總結以後得空再總結。 

############################statistics.R################################

#領券日期參數, 修改統計日參數
date_parameter <- "2016-07-11"
dayCount_parameter = 1


hiveContext <- sparkRHive.init(sc)
sql(hiveContext, "use honeycomb_bh_db")

#通過hiveSql 獲得想要的並集集合併且緩存下來 sql date_add
##程式執行階段1: 數據準備。。。。。
acquired_users_sql <-"select * from sc_t_acquire_record where sc_t_acquire_record.year=2016 and sc_t_acquire_record.month=07 and to_date(ct_time)='STARTDATE'"
all_order_sql <- "select * from sc_t_order_all_info As a where a.year=2016 and a.month=07 and to_date(a.create_time)>='STARTDATE' and to_date(a.create_time)<=date_add(date('STARTDATE'),14) and product_id=210"
rebate_order_sql <- "select * from sc_t_order_rebate_info As a where a.year=2016 and a.month=07 and to_date(a.create_time)>='STARTDATE' and to_date(a.create_time)<=date_add(date('STARTDATE'),7) and product_id=210"

acquired_users_sql<-sub(pattern='STARTDATE', replacement=date_parameter, acquired_users_sql)
all_order_sql<-gsub(pattern='STARTDATE', replacement=date_parameter, all_order_sql)
rebate_order_sql<-gsub(pattern='STARTDATE', replacement=date_parameter, rebate_order_sql)


#當天領券綁定的用戶集合
acquired_users <-sql(hiveContext,acquired_users_sql)
cache(acquired_users)

#15日內的全訂單集合
all_orders <-sql(hiveContext,all_order_sql)

#7日內返利的訂單集合
rebated_orders <- sql(hiveContext,rebate_order_sql)

#第0日領券後到14日結束前, 有打車紀錄的
acquired_users_with_orders<-join(acquired_users,all_orders, acquired_users$presentee_mobile==all_orders$passenger_phone, "left_outer")
acquired_users_with_orders <- filter(acquired_users_with_orders, "passenger_phone is not null")


mobiles_acquired_users <-distinct(select(acquired_users_with_orders, "presentee_mobile"))
#write.json(acquired_users_with_orders, "file:///home/rd/spark/bin/20160711_users_convertion.json")

#第0日領券後~第7日結束前,被返利的領券用戶
orders_rebated_within_8days <- join(acquired_users,rebated_orders, acquired_users$presentee_mobile==rebated_orders$passenger_phone, "left_outer")
orders_rebated_within_8days <- filter(orders_rebated_within_8days, "passenger_phone is not null")

cache(orders_rebated_within_8days)
results <- data.frame("name" = c("frist"), "value" = c(0),stringsAsFactors=FALSE)

##程式執行階段2: 開始利用spark進行集合運算。。。。。

#第0日到第7日結束前, 券有效期內打過車的領券用戶訂單數據
rules<- "to_date(a.create_time)>='STARTDATE' and to_date(a.create_time)<=date_add(date('STARTDATE'),7)"
rules<-gsub(pattern='STARTDATE', replacement=date_parameter, rules)
orders_within_8days = filter(acquired_users_with_orders, rules)
mobiles_with_orders_within_8days <- distinct(select(orders_within_8days, "presentee_mobile"))


#第8日到第14日結束前, 券過期後, 打過車的領券用戶訂單數據
rules<- "to_date(a.create_time)>=date_add(date('STARTDATE'),8) and to_date(a.create_time)<=date_add(date('STARTDATE'),15)"
rules<-gsub(pattern='STARTDATE', replacement=date_parameter, rules)
orders_after_8days = filter(acquired_users_with_orders, rules)
mobiles_with_orders_after_8days <- distinct(select(orders_after_8days, "presentee_mobile"))


#第0日到第7日結束前, 被返利信息紀錄的領券用戶
mobiles_user_reabted <-distinct(select(orders_rebated_within_8days, "presentee_mobile"))

#券0~7天有效期內首單後未被返利的用戶
mobiles_my_team_losted <- except(mobiles_with_orders_within_8days, mobiles_user_reabted)

#第8日券有效期過後, 14日內, 有成交紀錄被sic統計方法, 統計進來的用戶
mobiles_after_7days_countedBySicheng <-except(mobiles_with_orders_after_8days, mobiles_user_reabted)

#券0~7天有效期內首單後未被返利的用戶, 第8日到第14日成單, 被sic統計轉化的用戶
mobiles_my_team_losted_countedBySicheng <-intersect(mobiles_my_team_losted, mobiles_with_orders_after_8days)


#第8日券有效期過後, 14日內, 思成沒有統計的首單用戶
mobiles_both_losted <- except(mobiles_my_team_losted, mobiles_after_7days_countedBySicheng)

#券0~7天有效期內首單後未被返利, 後7天沒打車的用戶
mobile_first_order_withno_coupon_no_futher_order_after_7days <- except(mobiles_my_team_losted, mobiles_with_orders_after_8days)

#7日內沒打車, 後7日打車的用戶
mobiles_with_order_invoked_coupon <- except(mobiles_with_orders_after_8days, mobiles_with_orders_within_8days)

#領券後15天里打車的用戶, 由於業務特性,可以重覆領券 這個存在重覆統計。
mobiles_converted = acquired_users_with_orders

#程式運行階段: 輸出結果。。。
results<-rbind(results, c("領新手券的用戶數量", nrow(distinct(select(acquired_users, "presentee_mobile")))))
results<-rbind(results, c("領新手券後15日轉化的用戶數量", nrow(mobiles_acquired_users)))
results<-rbind(results, c("領新手券7日內打車用券轉化的用戶數量", nrow(mobiles_user_reabted)))
results<-rbind(results, c("新手券有效期過期後7日內打車轉化用戶", nrow(mobiles_after_7days_countedBySicheng)))
results<-rbind(results, c("sic統計方法統計的轉化用戶數", nrow(mobiles_user_reabted)+nrow(mobiles_after_7days_countedBySicheng)))
results<-rbind(results, c("7日內首單未用新手券的人數", nrow(mobiles_my_team_losted)))
results<-rbind(results, c("7日內首單未用新手券, 後7日內沒打車的人數", nrow(mobiles_both_losted)))
results<-rbind(results, c("7日內首單未用新手券, 後7日內有打車的人數", nrow(mobiles_my_team_losted_countedBySicheng)))

results<-rbind(results, c("領新手券後7日內未打車, 後7日又打車的人數", nrow(mobiles_with_order_invoked_coupon)))
results

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 利用SQl對資料庫實行數據拆分與組合實現提供以下幾種方案: 方法一: WITH CTE AS (SELECT A.Id,A.[Uid],UserName FROM (SELECT A.[id], REPLACE(Split.a.value('.', 'NVARCHAR(max)'),'''','') ...
  • 一、前言 近兩天項目升級數據遷移,將老版本(sqlserver)的數據遷移到新版本(mysql)資料庫,需要整理一個Excel表格出來,映射兩個庫之間的表格欄位,示例如下: Mysql資料庫查詢表結構很方便,用客戶端(SQLyog)可以直接複製出需要的表結構,據說可以用簡單的命令查詢表結構,但是不會 ...
  • mongodb一直都在不斷的更新,不斷的發展,那些非常好玩也非常實用的功能都逐步加入到了mongodb中,這不就有了本篇對ttlindex的介紹, 剛好我們的生產業務場景中就有這個一個案例。。。 一:案例分析 我們生產的推薦系統要給用戶發送簡訊和郵件的關聯營銷。第一波是:當用戶在淘寶上下訂單之後,我 ...
  • CHAR char是定長的,在欄位建立時,空間就固定了,不管是否插入值(NULL也包含在內),都占用字元的空間。例如: char(8),輸入字元小於8,後面補空值。輸入字元大於8時,會截取。CHAR存儲定長數據(英文或數字)很方便,CHAR欄位上的索引效率級高。 VARCHAR (n) 可變長且非 ...
  • 原文出處:https://blogs.msdn.microsoft.com/sqlcat/2013/09/16/top-10-sql-server-integration-services-best-practices/ 譯: 多少人聽說過“SQL Server Integration Servic ...
  • 一、資料庫結構的設計 如果不能設計一個合理的資料庫模型,不僅會增加客戶端和伺服器段程式的編程和維護的難度,而且將會影響系統實際運行的性能。所以,在一個系統開始實施之前,完備的資料庫模型的設計是必須的。 在一個系統分析、設計階段,因為數據量較小,負荷較低。我們往往只註意到功能的實現,而很難註意到性能的 ...
  • ①在運行中輸入regedit.exe,啟動註冊表工具 ②找到註冊表中的此處路徑“HKEY_CURRENT_USER\Software\Microsoft\SQL Server Management Studio” ③刪除11.0_Config文件夾 ④重新啟動sql server 2012 ...
  • This document is a starting point for users working with Hadoop Distributed File System (HDFS) either as a part of a Hadoop cluster or as a stand alon ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...