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;
Copy

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;
Copy

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;
Copy

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 em patient_id, a consulta falha porque não desduplica explicitamente.

SELECT COUNT(*)
  FROM patients
  WHERE insurance_type = 'Commercial';
Copy

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';
Copy
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';
Copy

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';
Copy

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;
Copy

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;
Copy

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'));
Copy

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'));
Copy

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'));
Copy

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'));
Copy

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      |
+-----------------------------------+--------------+---------------+--------------+