Como consultar dados protegidos por privacidade diferencial¶
Este tópico ajuda um analista a executar consultas em dados protegidos por privacidade diferencial (ou seja, tabelas e exibições protegidas por privacidade) e a entender e ajustar os resultados retornados pelas consultas.
Para executar uma consulta em uma tabela protegida por privacidade, um usuário deve ter privilégio SELECT na tabela.
Limitações
A privacidade diferencial oferece suporte a um subconjunto de tipos de dados, operadores, sintaxe de consulta e funções do Snowflake . Para obter uma lista de SQL suportado que você pode usar em uma consulta, consulte Referência de SQL da privacidade diferencial.
Consultas em tabelas protegidas por privacidade demoram mais porque o Snowflake precisa executar cálculos adicionais para determinar quanto ruído adicionar. Para consultas básicas, essa latência é de pelo menos 7 segundos. Consultas complexas, como as seguintes, podem levar muito mais tempo:
Consultas com muitas junções e subconsultas.
Consultas que saída várias linhas no resultado, por exemplo, ao usar cláusulas GROUP BY que resultam em centenas ou milhares de grupos.
Fundamentos de consulta¶
Esta seção discute os componentes básicos de uma consulta que será bem-sucedida quando executada em uma tabela protegida por privacidade. Isso inclui:
Agregação de dados¶
Todas as consultas em uma tabela protegida por privacidade devem agregar resultados em vez de recuperar registros individuais. Nem toda parte de uma consulta precisa usar uma função de agregação, desde que o resultado final seja agregado.
Com exceção de uma função COUNT, uma consulta não pode agregar uma coluna, a menos que a coluna tenha um domínio de privacidade.
Para obter uma lista de agregações suportadas, consulte Funções de agregação.
Uso de junções¶
As seções a seguir fornecem diretrizes para usar junções em uma consulta privada diferencial:
Para saber mais sobre as implicações que a união de duas tabelas protegidas por privacidade tem nos domínios de privacidade, consulte Domínios de privacidade e junções.
Operadores de junção¶
Cada junção deve ser uma junção equi que usa um único operador. Por exemplo, t1.c1 == t2.c1
é suportado, mas col1 > col2
e col1 + 10 = col2
não são. Junções não condicionadas não são suportadas.
As junções devem usar o operador JOIN. A sintaxe WHERE para junções não é suportada. Para obter mais informações sobre a sintaxe de junção, consulte Implementação de junções.
Junções suportadas¶
As junções em uma consulta privada diferencial devem ser uma das seguintes:
INNER
{ LEFT | RIGHT | FULL } OUTER
NATURAL
Ambos os lados da junção devem ter o mesmo padrão de consulta. Por exemplo, as seguintes junções são suportadas:
Ambos os lados são identificadores
SELECT COUNT(*) FROM t1 INNER JOIN t2 ON t1.a=t2.a;
Ambos os lados são subconsultas
SELECT COUNT(*) FROM (SELECT a, SUM(b) FROM t1 GROUP BY a) AS g1 INNER JOIN (SELECT * FROM t2) AS g2 ON g1.a=g2.a;
Atualmente, não há suporte para unir um identificador a uma subconsulta
Para obter informações sobre a sintaxe de consulta suportada relacionada a junções, consulte Sintaxe de consulta.
Uso de chaves de entidade em junções¶
Ao trabalhar com tabelas protegidas com privacidade em nível de entidade, você pode minimizar a quantidade de ruído incluindo a coluna de chave de entidade como parte da chave de junção, especialmente se isso não alterar semanticamente a consulta.
Por exemplo, considere as seguintes tabelas onde a entidade é clientes:
Tabela
Descrição
customers
Diretório de clientes, onde cada linha é um cliente e tem um
customer_id
.
transactions
Transações de clientes, onde cada cliente pode ter múltiplas transações.
transaction_lines
Itens exclusivos que foram comprados em uma transação. Pode haver várias linhas em uma única transação.
Se estiverem seguindo as práticas recomendadas, o provedor de dados estruturou os dados para que cada uma dessas tabelas tenha a chave de entidade customer_id
. Para esse esquema de dados, cada linha de transação só pode pertencer a uma transação e cada transação só pode pertencer a um cliente. Essa relação não é evidente nos próprios dados, portanto, sem informações adicionais, a quantidade de ruído adicionada para a privacidade diferencial será maior do que o necessário.
Você pode minimizar a quantidade de ruído incluindo a chave de entidade customer_id
como parte da chave de junção, mesmo que ela seja redundante. Por exemplo, unir a tabela transactions
a transaction_lines
normalmente requer apenas a chave de junção transaction_id
. No entanto, unir ambas transaction_id
e customer_id
resultará em uma quantidade menor de ruído.
Tipos de dados e domínios de privacidade¶
Ao unir duas tabelas, os tipos de dados das colunas de chave de junção de ambos os lados devem ser os mesmos. Para privacidade diferencial, o tipo de dados de uma coluna inclui se ela tem ou não um domínio de privacidade.
Por exemplo, se você tivesse uma tabela transactions
com privacidade protegida e uma tabela desprotegida product_lookup
e quisesse uni-las em product_id
, a coluna product_id
em ambas as tabelas deveria ser do mesmo tipo de dados (por exemplo, uma cadeia de caracteres) e cada uma deveria ter um domínio de privacidade.
Para atender a esse requisito, o administrador do analista pode precisar definir um domínio de privacidade assim como o provedor de dados o define. Para obter informações sobre como definir um domínio de privacidade para uma tabela, consulte Definição de um domínio de privacidade.
Requisito de exclusividade¶
As junções podem potencialmente duplicar linhas de dados, o que pode fazer com que a quantidade de ruído adicionada a um resultado de consulta se torne ilimitada. Para garantir que os dados protegidos por privacidade não sejam duplicados em uma junção, a chave de junção (ou seja, as colunas nas quais as tabelas são unidas) para tabelas protegidas por privacidade deve corresponder a apenas um registro na outra tabela. Isso significa que, ao unir-se a uma tabela protegida por privacidade, a chave de junção no lado oposto deve ser desduplicada.
Importante
O requisito de exclusividade para junções nem sempre se aplica a consultas em tabelas protegidas pela privacidade em nível de entidade. Para privacidade em nível de entidade, as consultas devem desduplicar na chave da entidade antes da agregação. Desde que isso seja feito após uma junção, mas antes da agregação, a junção não precisa ser feita em dados desduplicados. Para obter mais informações sobre como atender a esses requisitos, consulte Como consultar os dados protegidos pela privacidade em nível de entidade.
Para satisfazer o requisito de exclusividade para junções, a consulta pode usar um GROUP BY em um subconjunto das colunas de junção para agrupar linhas duplicadas em um resultado.
Por exemplo, suponha que a tabela patients
esteja protegida por privacidade diferencial e a tabela geo_lookup
não. O analista quer unir essas duas tabelas em zip_code
para poder filtrar a tabela patients
em State
. Para garantir que os registros na tabela patients
protegida por privacidade não sejam duplicados, a consulta deve desduplicar a tabela zip_code
na chave de junção. Isso deve ser feito explicitamente, mesmo que a tabela geo_lookup
já seja única em zip_code
. Isso garante que o Snowflake possa contabilizar corretamente a privacidade.
SELECT COUNT(*)
FROM patients
LEFT JOIN (SELECT zip_code, ANY_VALUE(state) AS residence_state
FROM geo_lookup
GROUP BY zip_code)
USING zip_code
WHERE birth_state = residence_state;
df_patients = session.table("patients")
df_geo = session.table("geo_lookup")
df_geo_deduped = df_geo.group_by("zip_code").agg(f.any_value("state").as_("state"))
df_patients.join(df_geo_deduped, on="zip_code", join_type="left")\
.where(f.col("birth_state") == f.col("residence_state")).select(f.count("*"))
Como consultar os dados protegidos pela privacidade em nível de entidade¶
A maioria dos provedores de dados usa uma chave de entidade para implementar a privacidade em nível de entidade ao configurar a privacidade diferencial. Quando uma tabela é protegida por privacidade em nível de entidade, o Snowflake não permite agregações em campos se houver um número ilimitado de linhas por entidade. Isso significa que as consultas devem atender aos seguintes requisitos:
Em algum ponto da consulta, a tabela protegida por privacidade deve ser desduplicada na chave de entidade. As operações que podem ser usadas para desduplicar dados são:
COUNT( DISTINCT <entity_key_column> )
GROUP BY <entity_key_column>
UNION (mas não UNION ALL) quando apenas a chave da entidade é projetada.
Se uma junção usar uma chave de junção diferente da coluna de chave de entidade, essa junção não poderá ocorrer entre a desduplicação e a cláusula SELECT final com agregação.
Nota
Se o provedor de dados implementou a privacidade em nível de linha, o requisito de desduplicação para junções é diferente. Para obter mais informações sobre esses requisitos, consulte Requisito de exclusividade.
Para ajudar a ilustrar os requisitos de privacidade em nível de entidade, suponha que você tenha uma tabela protegida por privacidade patients
om a coluna de chave de entidade patient_id
. Você também tem uma tabela geo_lookup
não sensível e desprotegida. Os exemplos a seguir mostram uma consulta que falha seguida de uma versão reescrita que é bem-sucedida.
- Exemplo: desduplicação
A consulta a seguir falha porque não atende ao requisito de desduplicação. Mesmo que a tabela
patients
já seja única empatient_id
, a consulta falha porque não desduplica explicitamente.SELECT COUNT(*) FROM patients WHERE insurance_type = 'Commercial';
Para reescrever a consulta de modo que ela seja bem-sucedida, inclua uma contagem distinta na coluna da chave da entidade para desduplicar explicitamente a chave da entidade. Por exemplo:
SELECT COUNT(DISTINCT patient_id) FROM patients WHERE insurance_type = 'Commercial';
- Exemplo: localização da junção
A consulta a seguir falha mesmo usando uma cláusula GROUP BY para atender ao requisito de desduplicação. Falha porque a tabela está sendo unida a outra tabela usando uma coluna que não é a coluna de chave da entidade.
SELECT AVG(bmi) FROM (SELECT patient_id, ANY_VALUE(zip_code) AS zip_code FROM patients GROUP BY patient_id) AS p JOIN geo_lookup AS g ON p.zip_code = g.zip_code WHERE state='CA';
Para reescrever a consulta para que ela seja bem-sucedida, use a cláusula GROUP BY após a junção. A junção não pode ocorrer entre a desduplicação e a cláusula SELECT com agregação.
SELECT AVG(bmi) FROM (SELECT patient_id, ANY_VALUE(bmi) as bmi, ANY_VALUE(state) as state FROM patients AS p JOIN geo_lookup AS g ON p.zip_code = g.zip_code GROUP BY patient_id) WHERE state='CA';
Execução de consultas em nível de transação¶
O requisito de desduplicação para privacidade diferencial em nível de entidade não impede que você execute consultas em nível de transação. No entanto, primeiro você deve agrupar os dados no nível da entidade e depois agregar nesses grupos.
Por exemplo, suponha que você tenha uma tabela doctor_visits
e que o provedor de dados tenha definido uma chave de entidade patient_id
para implementar privacidade em nível de entidade. Uma consulta em nível de transação pode ser: “Quantas consultas médicas não foram para um check-up regular?” A seguir está um exemplo de como escrever esta consulta:
SELECT SUM(num_visits)
FROM (SELECT SUM((visit_reason<>'Regular checkup')::INT) AS num_visits
WHERE visit_reason IS NOT NULL
GROUP BY patient_id)
WHERE num_visits > 0 AND num_visits < 20;
A subconsulta faz um agrupamento por patient_id
para desduplicar os dados. A coluna agregada num_visits
captura o número de visitas por paciente que não foram para um check-up regular. A consulta então agrega novamente essa coluna por paciente para obter o número total de visitas. Observe que a cláusula WHERE na consulta externa é necessária para especificar um domínio de privacidade nos dados.
Nota
Embora não seja um requisito, uma prática recomendada ao unir tabelas protegidas por privacidade diferencial em nível de entidade é incluir a coluna da chave da entidade como parte da chave de união (se isso não alterar semanticamente a consulta). Para obter mais informações, consulte Uso de chaves de entidade em junções.
Como entender os resultados de consulta¶
Consultas em uma tabela protegida por privacidade não retornam o valor exato de uma agregação. A privacidade diferencial introduz ruído no resultado, tornando-o uma aproximação do valor real. O valor retornado difere o suficiente do valor real para ocultar se os dados de um indivíduo estão incluídos na agregação. Isso se aplica a todas as consultas, exceto para uma consulta que retorna o número total de linhas na tabela protegida por privacidade, por exemplo, SELECT COUNT(*) FROM t
.
Um analista precisa ser capaz de determinar se o ruído introduzido no resultado diminuiu a utilidade da consulta. A Snowflake usa um intervalo de ruído para ajudar os analistas a interpretar os resultados. Um intervalo de ruído é um intervalo matemático fechado que, na maioria dos casos, inclui o valor real da agregação. Há 95% de chance de que o resultado real de uma consulta esteja dentro do intervalo de ruído.
Adicionar as seguintes funções a uma consulta permite que o analista use o intervalo de ruído para tomar decisões sobre a utilidade de uma consulta:
DP_INTERVAL_LOW — Retorna o limite inferior do intervalo de ruído. O valor real provavelmente será igual ou maior que esse número.
DP_INTERVAL_HIGH — Retorna o limite superior do intervalo de ruído. O valor real provavelmente será igual ou menor que esse número.
Para usar essas funções, passe o alias de uma coluna agregada na consulta principal. Por exemplo, a consulta a seguir retorna a soma da coluna num_claims
junto com o intervalo de ruído para essa agregação:
SELECT SUM(num_claims) AS sum_claims,
DP_INTERVAL_LOW(sum_claims),
DP_INTERVAL_HIGH(sum_claims)
FROM t1;
dp_interval_low = f.function('dp_interval_low')
dp_interval_high = f.function('dp_interval_high')
dpdf_cohort.group_by().agg(f.sum("num_claims").alias("sum_claims"),
dp_interval_low("sum_claims"),
dp_interval_low("sum_claims")
).show()
A saída pode ser:
+--------------+--------------------------------+----------------------------------+
| sum_claims | dp_interval_low("sum_claims") | dp_interval_high("sum_claims") |
|--------------+--------------------------------+----------------------------------+
| 50 | 35 | 75 |
+--------------+--------------------------------+----------------------------------+
Neste caso, o valor de retorno é uma soma de 50. Mas o analista também determinou com 95% de certeza que o valor real da agregação está entre 35 e 75.
Dica
Para obter informações sobre técnicas que podem reduzir potencialmente o ruído nos resultados, consulte
Acompanhamento dos gastos do orçamento de privacidade¶
Você pode usar a função ESTIMATE_REMAINING_DP_AGGREGATES para estimar quantas consultas adicionais você pode executar dentro da janela de orçamento atual (ou seja, até que a perda cumulativa de privacidade seja redefinida para 0). A estimativa é baseada no número de agregados, não de consultas. Por exemplo, a consulta SELECT SUM(age), COUNT(age) FROM T
contém duas funções agregadas: SUM(age)
e COUNT(age)
.
Ao executar a função ESTIMATE_REMAINING_DP_AGGREGATES, certifique-se de usar as mesmas condições que você está usando para executar consultas, por exemplo, o mesmo usuário, função e conta.
Se estiver executando uma consulta que usa várias tabelas, você deverá executar ESTIMATE_REMAINING_DP_AGGREGATES uma vez por tabela e, em seguida, usar o menor valor NUMBER_OF_REMAINING_DP_AGGREGATES
como limite de uso estimado.
O exemplo a seguir mostra como uma série de consultas afeta quanto do limite do orçamento de privacidade foi gasto (ou seja, a perda cumulativa de privacidade das consultas) e o número estimado de agregados restantes.
1. Verificação inicial
Vejamos os números do orçamento de privacidade na tabela my_table
. Você nunca executou nenhuma consulta nesta tabela.
SELECT * FROM TABLE(SNOWFLAKE.DATA_PRIVACY.ESTIMATE_REMAINING_DP_AGGREGATES('my_table'));
Nenhum orçamento utilizado até agora:
+-----------------------------------+--------------+---------------+--------------+
| NUMBER_OF_REMAINING_DP_AGGREGATES | BUDGET_LIMIT | BUDGET_WINDOW | BUDGET_SPENT |
|-----------------------------------+--------------+---------------+--------------|
| 996 | 233 | WEEKLY | 0.0 |
+-----------------------------------+--------------+---------------+--------------+
2. Execução de uma consulta
Vamos executar uma consulta com uma função de agregação e verificar nossos números novamente:
SELECT SUM(salary) FROM my_table;
-- results omitted ...
SELECT * FROM TABLE(SNOWFLAKE.DATA_PRIVACY.ESTIMATE_REMAINING_DP_AGGREGATES('my_table'));
A estimativa de chamadas agregadas restantes caiu para um e a perda cumulativa de privacidade (orçamento gasto) aumentou.
+-----------------------------------+--------------+---------------+--------------+
| NUMBER_OF_REMAINING_DP_AGGREGATES | BUDGET_LIMIT | BUDGET_WINDOW | BUDGET_SPENT |
|-----------------------------------+--------------+---------------+--------------|
| 995 | 233 | WEEKLY | 0.6 |
+-----------------------------------+--------------+---------------+--------------+
3. Execução de outra consulta com duas funções agregadas
SELECT SUM(age), COUNT(age) FROM my_table GROUP BY STATE;
-- results omitted ...
SELECT * FROM TABLE(SNOWFLAKE.DATA_PRIVACY.ESTIMATE_REMAINING_DP_AGGREGATES('my_table'));
A estimativa de consultas restantes caiu para dois. Lembre-se, esta é uma estimativa.
+-----------------------------------+--------------+---------------+--------------+
| NUMBER_OF_REMAINING_DP_AGGREGATES | BUDGET_LIMIT | BUDGET_WINDOW | BUDGET_SPENT |
|-----------------------------------+--------------+---------------+--------------|
| 993 | 233 | WEEKLY | 1.8 |
+-----------------------------------+--------------+---------------+--------------+
4. Execução de uma consulta novamente
Vamos executar novamente uma consulta anterior para mostrar que o orçamento de privacidade é sempre cobrado, mesmo em consultas idênticas. Uma consulta duplicada incorre na mesma perda de privacidade toda vez que é executada (ou seja, gasta a mesma quantidade de orçamento de privacidade).
SELECT SUM(age), COUNT(age) FROM T GROUP BY STATE;
-- results omitted ...
SELECT * FROM TABLE(SNOWFLAKE.DATA_PRIVACY.ESTIMATE_REMAINING_DP_AGGREGATES('my_table'));
Mesma cobrança pela consulta de antes: 1,2 unidades de perda de privacidade.
+-----------------------------------+--------------+---------------+--------------+
| NUMBER_OF_REMAINING_DP_AGGREGATES | BUDGET_LIMIT | BUDGET_WINDOW | BUDGET_SPENT |
|-----------------------------------+--------------+---------------+--------------|
| 991 | 233 | WEEKLY | 3.0 |
+-----------------------------------+--------------+---------------+--------------+