Implementação de análise de rastreamento de linhagem de tabela SQL com base em Python-sqlparse

Índice

prefácio

A principal tarefa

1. Governança de Dados

2. Rastreamento de linhagem

3. Sangue da tabela SQL

Em segundo lugar, o processo de realização

1. Efeito alvo

2. Implementação do código

1. Identificação da função função

2. Formato padrão SQL

 3. Analise a árvore AST

4. Efeito final:

Preste atenção, evite se perder, se houver algum erro, por favor deixe uma mensagem para aconselhamento, muito obrigado


prefácio

Anteriormente, eu disse em dois artigos sobre a análise de biblioteca de código aberto do SQLparse que estava procurando uma análise de linhagem SQL viável na programação python. Se JAVA é usado para analisar a prática de código-fonte do Hive, ainda pretendo fazê-lo em um estágio posterior. Primeiro , deixe o Python ser capaz de implementá-lo. Conclua-o primeiro. A principal razão é que a camada inferior do HiveSQL é o código JAVA, como reescrevê-lo ainda não pode contornar o JAVA. No entanto, eu mencionei sqlparse na série anterior. Na verdade, não é impossível para esta biblioteca analisar sangue, mas as funções que podem ser realizadas são limitadas. No momento, meu experimento está OK, e alguns SQLs mais complexos também podem ser analisado. Pode-se considerar que atingiu com sucesso o nível de serviços implementáveis, mas se for correspondido de acordo com o formato SQL, deve haver alguns formatos SQL que não podem ser totalmente correspondidos com sucesso. Se você tiver SQL que precisa de análise de relacionamento de sangue , você pode verificá-lo novamente.

Considera-se que alguns dos poços anteriores foram preenchidos.O progresso do desenvolvimento atual foi capaz de rastrear a análise do relacionamento sangue da tabela SQL, e o desenvolvimento da função para realizar o relacionamento sangue do campo será lançado um após o outro.


A principal tarefa

Em primeiro lugar, vamos analisar os objetivos do projeto.Quando se trata de análise de linhagem SQL, isso é tendencioso para a governança de dados.

1. Governança de Dados

A Governança de Dados é um conjunto de comportamentos gerenciais que envolvem o uso de dados em uma organização. Para gerar valor a partir de dados, é necessário um "objetivo de negócios" razoável. Todas as atividades de governança de dados devem ser realizadas em torno de objetivos de negócios reais. Estabelecer padrões de dados e melhorar a qualidade dos dados são apenas meios, não metas.

A essência da governança de dados é gerenciar os dados, por isso é necessário fortalecer o gerenciamento de metadados e o gerenciamento de dados mestre, gerenciar os dados da fonte e complementar atributos e informações relevantes dos dados, como: metadados, qualidade, segurança, lógica de negócios, relação de sangue, etc., por meio de metadados Uma abordagem orientada por dados para gerenciar a produção, processamento e uso de dados.

A qualidade dos dados afeta diretamente o valor dos dados e afeta diretamente os resultados da análise de dados e a qualidade das decisões que tomamos com base neles. A consistência da linhagem do modelo de dados e do agendamento de tarefas é a chave para a integração da construção e gerenciamento, o que ajuda a resolver o problema de gerenciamento de dados inconsistente e calibres de produção de dados, e evita o surgimento de um modelo de gerenciamento ineficiente com gerenciamento dual inconsistente.

2. Rastreamento de linhagem

Quando os dados são usados ​​em cenários de negócios e são encontrados erros de dados, a equipe de governança de dados precisa localizar rapidamente a fonte de dados e corrigir os erros de dados. Em seguida, a equipe de governança de dados precisa saber de qual biblioteca principal os dados da equipe de negócios vêm e de qual fonte de dados os dados da biblioteca principal vêm. Nossa prática é estabelecer uma relação de associação entre os metadados e a lista de recursos de dados, e os itens de dados utilizados pela equipe de negócios são configurados pela combinação dos metadados, de modo que a relação de sangue entre o cenário de uso de dados e a fonte de dados seja estabelecido. Catálogo de recursos de dados: o catálogo de recursos de dados geralmente é usado em cenários de compartilhamento de dados, como compartilhamento de dados entre departamentos governamentais. O catálogo de recursos de dados é criado com base em cenários de negócios e especificações do setor e é automatizado com base em metadados e temas básicos de biblioteca. aplicação e uso.

É por isso que precisamos analisar SQL, rastrear indexação de tabela ou análise de referência.

3. Sangue da tabela SQL

Então o mais importante é sobre o relacionamento de dados entre os vários bancos de dados. As operações de construção e inserção e atualização de tabelas causarão certas alterações nos dados, então essas operações devem ser permitidas? Assim como o programador de uma determinada empresa que vi na internet apagou a biblioteca e fugiu, ou apagou acidentalmente os dados errados, o que atrasou a linha de produção e pesquisa, etc. Para evitar a ocorrência dos acidentes acima, é necessário ter uma camada de seguro para esta operação e definir permissões de operação de dados para cada membro. Dessa forma, a instrução SQL enviada tem mais uma camada de julgamento.

Em segundo lugar, o processo de realização

1. Efeito alvo

Antes de mais nada, precisamos entender qual formulário precisamos fazer. Entre eles, o SQLFlow é, sem dúvida, a primeira fila do setor:

 Quando vi essa foto pela primeira vez, decidi que o rastreamento de linhagem deveria ser assim, que pode analisar claramente a relação de linhagem entre cada campo e tabela. Com isso, definimos o benchmark para a saída, e o objetivo do projeto que vamos fazer é exatamente isso.

 

2. Implementação do código

1. Identificação da função função

Essa função também é uma função que deve ser implementada, precisamos entender o que esse SQL faz principalmente. Se for um INSERT ou CREATE, é necessário analisar a relação de sangue, se for um SELECT, pode-se fazer uma análise SQL simples. Com os resultados do estudo do código-fonte sqlparse, podemos chamar a função correspondente:

sql="select * from table1;insert into table select a,b,c from table2"

if __name__ == '__main__':
    table_names=[]
    #sql=get_sqlstr('read_sql.txt')
    stmt_tuple=analysis_statements(sql)
    for each_stmt in stmt_tuple:
        type_name=get_main_functionsql(each_stmt)
        print(type_name)

resultado:

 

 Então, para SELECT, podemos rastrear as tabelas envolvidas no SQL:

Para CREATE e INSERT, a relação de sangue pode ser feita:

2. Formato padrão SQL

Para SQL de entrada, devemos primeiro tornar essa instrução em conformidade com o formato de instrução SQL padrão, para que o formato de transmissão seja consistente e compatível. Normalmente lemos através do texto. Portanto, você precisa ler o texto para processamento:

Texto original:

 Após o processamento:

if __name__ == '__main__':
    sql=get_sqlstr('read_sql.txt')
    print(sql)

 3. Analise a árvore AST

O SQL resultante, seja ANTRL ou SQLPARSE, é analisado em uma árvore para retrocesso recursivo. No final, a árvore SQL de produção deve ser analisada:

sql="select * from table1;insert into table3 select a,b,c from table2"

if __name__ == '__main__':
    #sql=get_sqlstr('read_sql.txt')
    stmt_tuple=analysis_statements(sql)
    for each_stmt in stmt_tuple:
        table_names=[]
        type_name=get_main_functionsql(each_stmt)
        get_ASTTree(each_stmt)

 

4. Efeito final:

SQL:


select
b.product_name "产品",
count(a.order_id) "订单量",
b.selling_price_max "销售价",
b.gross_profit_rate_max/100 "毛利率",
case when b.business_type =1 then '自营消化' when b.business_type =2 then '服务商消化'  end "消化模式"
from(select 'CRM签单' label,date(d.update_ymd) close_ymd,c.product_name,c.product_id,
    a.order_id,cast(a.recipient_amount as double) amt,d.cost
    from mysql4.dataview_fenxiao.fx_order a
    left join mysql4.dataview_fenxiao.fx_order_task b on a.order_id = b.order_id
    left join mysql7.dataview_trade.ddc_product_info c on cast(c.product_id as varchar) = a.product_ids and c.snapshot_version = 'SELLING'
    inner join (select t1.par_order_id,max(t1.update_ymd) update_ymd,
                sum(case when t4.product2_type = 1 and t5.shop_id is not null then t5.price else t1.order_hosted_price end) cost
               from hive.bdc_dwd.dw_mk_order t1
               left join hive.bdc_dwd.dw_mk_order_status t2 on t1.order_id = t2.order_id and t2.acct_day = substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2)
               left join mysql7.dataview_trade.mk_order_merchant t3 on t1.order_id = t3.order_id
               left join mysql7.dataview_trade.ddc_product_info t4 on t4.product_id = t3.MERCHANT_ID and t4.snapshot_version = 'SELLING'
               left join mysql4.dataview_scrm.sc_tprc_product_info t5 on t5.product_id = t4.product_id and t5.shop_id = t1.seller_id
               where t1.acct_day = substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2)
               and t2.valid_state in (100,200) ------有效订单
               and t1.order_mode = 10    --------产品消耗订单
               and t2.complete_state = 1  -----订单已经完成
               group by t1.par_order_id
    ) d on d.par_order_id  = b.task_order_id
    where c.product_type = 0 and date(from_unixtime(a.last_recipient_time)) > date('2016-01-01') and a.payee_type <> 1 -----------已收款
    UNION ALL
    select '企业管家消耗' label,date(c.update_ymd) close_ymd,b.product_name,b.product_id,
    a.task_id,(case when a.yb_price = 0 and b.product2_type = 1 then b.selling_price_min else a.yb_price end) amt,
    (case when a.yb_price = 0 and b.product2_type = 2 then 0 when b.product2_type = 1 and e.shop_id is not null then e.price else c.order_hosted_price end) cost
    from mysql8.dataview_tprc.tprc_task a
    left join mysql7.dataview_trade.ddc_product_info b on a.product_id = b.product_id and b.snapshot_version = 'SELLING'
    inner join hive.bdc_dwd.dw_mk_order c on a.order_id = c.order_id and c.acct_day = substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2)
    left join hive.bdc_dwd.dw_mk_order_status d on d.order_id = c.order_id and d.acct_day = substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2)
    left join mysql4.dataview_scrm.sc_tprc_product_info e on e.product_id = b.product_id and e.shop_id = c.seller_id
    where  d.valid_state in (100,200) and d.complete_state = 1  and c.order_mode = 10
    union ALL
    select '交易管理系统' label,date(t6.close_ymd) close_ymd,t4.product_name,t4.product_id,
    t1.order_id,(t1.order_hosted_price-t1.order_refund_price) amt,
    (case when t1.order_mode <> 11 then t7.user_amount when t1.order_mode = 11 and t4.product2_type = 1 and t5.shop_id is not null then t5.price else t8.cost end) cost
    from hive.bdc_dwd.dw_mk_order t1
    left join hive.bdc_dwd.dw_mk_order_business t2 on t1.order_id = t2.order_id and t2.acct_day=substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2)
    left join mysql7.dataview_trade.mk_order_merchant t3 on t1.order_id = t3.order_id
    left join mysql7.dataview_trade.ddc_product_info t4 on t4.product_id = t3.MERCHANT_ID and t4.snapshot_version = 'SELLING'
    left join mysql4.dataview_scrm.sc_tprc_product_info t5 on t5.product_id = t4.product_id and t5.shop_id = t1.seller_id
    left join hive.bdc_dwd.dw_fact_task_ss_daily t6 on t6.task_id = t2.task_id and t6.acct_time=date_format(date_add('day',-1,current_date),'%Y-%m-%d')
    left join (select a.task_id,sum(a.user_amount) user_amount
               from hive.bdc_dwd.dw_fn_deal_asyn_order a
               where a.is_new=1 and a.service='Trade_Payment' and a.state=1 and a.acct_day=substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2)
               group by a.task_id)t7 on t7.task_id = t2.task_id          
    left join (select t1.par_order_id,sum(t1.order_hosted_price - t1.order_refund_price) cost
               from hive.bdc_dwd.dw_mk_order t1
               where t1.acct_day = substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2) and t1.order_type = 1 and t1.order_stype = 4 and t1.order_mode = 12
               group by t1.par_order_id) t8 on t1.order_id = t8.par_order_id
    where t1.acct_day = substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2)
    and t1.order_type = 1 and t1.order_stype in (4,5) and t1.order_mode <> 12 and t4.product_id is not null and t1.order_hosted_price > 0 and t6.is_deal = 1 and t6.close_ymd >= '2018-12-31'
)a
left join mysql7.dataview_trade.ddc_product_info b on a.product_id = b.product_id and b.snapshot_version = 'SELLING'
where b.product2_type = 1 -------标品
and close_ymd between DATE_ADD('day',-7,CURRENT_DATE)  and DATE_ADD('day',-1,CURRENT_DATE)
GROUP BY b.product_name,
b.selling_price_max,
b.gross_profit_rate_max/100,
b.actrul_supply_num,
case when b.business_type =1 then '自营消化' when b.business_type =2 then '服务商消化'  end
order by count(a.order_id) desc
limit 10
if __name__ == '__main__':
    table_names=[]
    sql=get_sqlstr('read_sql.txt')
    
    stmt_tuple=analysis_statements(sql)
    for each_stmt in stmt_tuple:
        type_name=get_main_functionsql(each_stmt)
        blood_table(each_stmt)
        Tree_visus(table_names,type_name)
        

 

Preste atenção, evite se perder, se houver algum erro, por favor deixe uma mensagem para aconselhamento, muito obrigado

Isso é tudo para esta questão. Estou fã, se você tiver alguma dúvida, sinta-se à vontade para deixar uma mensagem para discutir, vejo você na próxima edição

Acho que você gosta

Origin blog.csdn.net/master_hunter/article/details/127387722
Recomendado
Clasificación