> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-parallel-read-in-order-multi-part.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Explore o ClickHouse com um conjunto de dados sobre bilhões de viagens de táxi e de veículos de transporte por aplicativo (Uber, Lyft etc.) com origem na cidade de Nova York desde 2009

# Análise geoespacial com o conjunto de dados de táxis de Nova York

export const RunnableCode = ({children, run = false, showStats = true}) => {
  const [results, setResults] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(false);
  const [showResults, setShowResults] = useState(false);
  const [stats, setStats] = useState(null);
  const [isDark, setIsDark] = useState(false);
  const [hoveredRow, setHoveredRow] = useState(-1);
  const codeRef = useRef(null);
  useEffect(() => {
    if (typeof window !== "undefined") {
      const check = () => setIsDark(document.documentElement.classList.contains("dark"));
      check();
      const observer = new MutationObserver(check);
      observer.observe(document.documentElement, {
        attributes: true,
        attributeFilter: ["class"]
      });
      return () => observer.disconnect();
    }
  }, []);
  useEffect(() => {
    if (codeRef.current) {
      const block = codeRef.current.querySelector(".code-block");
      if (block) {
        block.style.marginBottom = "0";
        block.style.marginTop = "0";
        block.style.borderBottomLeftRadius = "0";
        block.style.borderBottomRightRadius = "0";
      }
    }
  });
  const getSqlText = () => {
    if (!codeRef.current) return "";
    const code = codeRef.current.querySelector("code");
    return (code || codeRef.current).textContent.trim();
  };
  const executeQuery = async () => {
    const sql = getSqlText();
    if (!sql) return;
    setLoading(true);
    setError(null);
    setResults(null);
    setShowResults(true);
    try {
      const cleanQuery = sql.replace(/;$/, "").trim();
      const params = new URLSearchParams({
        query: cleanQuery,
        default_format: "JSONCompact",
        result_overflow_mode: "break",
        read_overflow_mode: "break",
        allow_experimental_analyzer: "1"
      });
      const res = await fetch(`https://sql-clickhouse.clickhouse.com/?${params.toString()}`, {
        method: "POST",
        headers: {
          Authorization: `Basic ${btoa(`demo:`)}`
        }
      });
      const text = await res.text();
      if (!res.ok) {
        setError(text || `HTTP ${res.status}`);
        setLoading(false);
        return;
      }
      const json = JSON.parse(text);
      setResults(json);
      setStats(json.statistics || null);
    } catch (err) {
      setError(err.message || "Falha na execução da consulta");
    }
    setLoading(false);
  };
  useEffect(() => {
    if (run) executeQuery();
  }, []);
  const formatRows = n => {
    if (n >= 1e9) return `${(n / 1e9).toFixed(1)}B`;
    if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
    if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
    return String(n);
  };
  const formatBytes = b => {
    if (b >= 1e9) return `${(b / 1e9).toFixed(2)} GB`;
    if (b >= 1e6) return `${(b / 1e6).toFixed(2)} MB`;
    if (b >= 1e3) return `${(b / 1e3).toFixed(2)} KB`;
    return `${b} B`;
  };
  const isNumericType = type => {
    return (/^(UInt|Int|Float|Decimal)/).test(type);
  };
  const isHyperlink = value => {
    return typeof value === "string" && (/^https?:\/\//).test(value);
  };
  const computeColumnExtremes = (meta, data) => {
    const extremes = {};
    for (let i = 0; i < meta.length; i++) {
      if (isNumericType(meta[i].type)) {
        let min = Infinity, max = -Infinity;
        for (const row of data) {
          const v = Number(row[i]);
          if (!isNaN(v)) {
            if (v < min) min = v;
            if (v > max) max = v;
          }
        }
        if (max > -Infinity) {
          extremes[i] = {
            min,
            max
          };
        }
      }
    }
    return extremes;
  };
  const computeColumnWidths = (meta, data) => {
    const lengths = meta.map((col, i) => {
      const headerLen = col.name.length + col.type.length + 1;
      let maxData = 0;
      for (const row of data) {
        const v = row[i];
        const len = v === null ? 4 : String(v).length;
        if (len > maxData) maxData = len;
      }
      return Math.max(headerLen, maxData);
    });
    const total = lengths.reduce((s, l) => s + l, 0);
    return lengths.map(l => `${(l / total * 100).toFixed(1)}%`);
  };
  const copyResultsAsTSV = () => {
    if (!results || !results.meta || !results.data) return;
    const header = results.meta.map(col => col.name).join("\t");
    const rows = results.data.map(row => row.map(cell => cell === null ? "NULL" : String(cell)).join("\t"));
    const tsv = [header, ...rows].join("\n");
    navigator.clipboard.writeText(tsv);
  };
  const borderColor = isDark ? "rgba(255,255,255,0.15)" : "#e5e7eb";
  const bgColor = isDark ? "rgba(255,255,255,0.05)" : "#f9fafb";
  const headerBg = isDark ? "#2a2a2a" : "#f3f4f6";
  const textColor = isDark ? "#e5e7eb" : "#1f2937";
  const mutedColor = isDark ? "#d1d5db" : "#6b7280";
  const accentColor = isDark ? "#FAFF69" : "#323232";
  const accentTextColor = isDark ? "#000" : "#fff";
  const barColor = isDark ? "#35372f" : "#d2d2d2";
  const cellBg = isDark ? "#1f201b" : "#ffffff";
  const cellBgHover = isDark ? "lch(15.8 0 0)" : "#f0f0f0";
  const extremes = results && results.meta && results.data ? computeColumnExtremes(results.meta, results.data) : {};
  const colWidths = results && results.meta && results.data ? computeColumnWidths(results.meta, results.data) : [];
  const getCellBarStyle = (cell, ci, ri) => {
    if (cell === null) return null;
    const colMeta = results.meta[ci];
    if (!isNumericType(colMeta.type) || !extremes[ci] || results.data.length <= 1 || extremes[ci].max <= 0) return null;
    const ratio = 100 * Number(cell) / extremes[ci].max;
    const bg = ri === hoveredRow ? cellBgHover : cellBg;
    return {
      background: `linear-gradient(to right, ${barColor} 0%, ${barColor} ${ratio}%, ${bg} ${ratio}%, ${bg} 100%)`
    };
  };
  const renderCell = (cell, ci) => {
    if (cell === null) {
      return <span style={{
        color: mutedColor,
        fontStyle: "italic"
      }}>NULL</span>;
    }
    const value = String(cell);
    if (isHyperlink(value)) {
      return <a href={value} target="_blank" rel="noopener noreferrer" style={{
        color: accentColor,
        textDecoration: "underline",
        cursor: "pointer"
      }}>
          {value}
        </a>;
    }
    return value;
  };
  return <div className="not-prose" style={{
    margin: "1rem 0",
    width: "100%",
    boxSizing: "border-box",
    contain: "inline-size"
  }}>
      {}
      <div>
        <div ref={codeRef}>{children}</div>

        {}
        <div style={{
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
    padding: "6px 12px",
    backgroundColor: headerBg,
    borderWidth: "0 1px 1px 1px",
    borderStyle: "solid",
    borderColor: isDark ? "rgba(255,255,255,0.1)" : "rgba(11,11,11,0.1)",
    borderRadius: "0 0 4px 4px"
  }}>
          <div style={{
    display: "flex",
    alignItems: "center",
    gap: "12px"
  }}>
            {results && <button onClick={() => setShowResults(!showResults)} style={{
    background: "none",
    border: "none",
    cursor: "pointer",
    color: mutedColor,
    fontSize: "12px",
    padding: "2px 4px"
  }}>
                {showResults ? "▼ Ocultar resultados" : "▶ Mostrar resultados"}
              </button>}
            {showStats && stats && <span style={{
    fontSize: "11px",
    color: mutedColor,
    fontStyle: "italic"
  }}>
                Foram lidas {formatRows(stats.rows_read)} linhas, {formatBytes(stats.bytes_read)} em {stats.elapsed.toFixed(3)}s
              </span>}
          </div>
          <button onClick={() => executeQuery()} disabled={loading} style={{
    display: "flex",
    alignItems: "center",
    gap: "6px",
    padding: "4px 14px",
    borderRadius: "4px",
    border: "none",
    cursor: loading ? "wait" : "pointer",
    backgroundColor: accentColor,
    color: accentTextColor,
    fontSize: "12px",
    fontWeight: 600
  }}>
            {loading ? <span>Em execução...</span> : <>
                <span style={{
    fontSize: "10px"
  }}>▶</span>
                <span>Executar</span>
              </>}
          </button>
        </div>
      </div>

      {}
      {showResults && <div className="not-prose" style={{
    marginTop: "8px",
    maxHeight: "350px",
    overflow: "auto",
    border: `1px solid ${borderColor}`,
    borderRadius: "4px"
  }}>
          <div>
            {loading && <div style={{
    padding: "24px",
    textAlign: "center",
    color: mutedColor
  }}>Executando consulta...</div>}

            {error && <div style={{
    padding: "12px 16px",
    color: "#ef4444",
    backgroundColor: isDark ? "rgba(239,68,68,0.1)" : "#fef2f2",
    fontSize: "13px",
    fontFamily: "monospace",
    whiteSpace: "pre-wrap"
  }}>
                {error}
              </div>}

            {results && results.meta && results.data && <div style={{
    display: "grid",
    gridTemplateColumns: colWidths.join(" "),
    width: "100%",
    fontSize: "13px",
    fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace'
  }}>
                {results.meta.map((col, i) => <div key={`h-${i}`} style={{
    position: "sticky",
    top: 0,
    zIndex: 1,
    padding: "6px 12px",
    textAlign: isNumericType(col.type) && results.meta.length > 1 ? "right" : "left",
    backgroundColor: headerBg,
    borderBottom: `1px solid ${borderColor}`,
    color: textColor,
    fontWeight: 600,
    fontSize: "12px",
    whiteSpace: "nowrap",
    overflow: "hidden",
    textOverflow: "ellipsis"
  }}>
                    {col.name}
                    <span style={{
    color: mutedColor,
    fontWeight: 400,
    marginLeft: "4px",
    fontSize: "10px"
  }}>{col.type}</span>
                  </div>)}
                {results.data.map((row, ri) => row.map((cell, ci) => <div key={`${ri}-${ci}`} onMouseEnter={() => setHoveredRow(ri)} onMouseLeave={() => setHoveredRow(-1)} style={{
    padding: "4px 12px",
    color: textColor,
    whiteSpace: "nowrap",
    overflow: "hidden",
    textOverflow: "ellipsis",
    textAlign: isNumericType(results.meta[ci].type) && results.meta.length > 1 ? "right" : "left",
    borderBottom: `1px solid ${borderColor}`,
    backgroundColor: ri === hoveredRow ? cellBgHover : ri % 2 === 0 ? "transparent" : bgColor,
    ...getCellBarStyle(cell, ci, ri)
  }}>
                      {renderCell(cell, ci)}
                    </div>))}
              </div>}

            {results && results.data && <div style={{
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
    padding: "4px 12px",
    fontSize: "11px",
    color: mutedColor,
    borderTop: `1px solid ${borderColor}`,
    backgroundColor: headerBg
  }}>
                <span>
                  {results.rows} linha{results.rows !== 1 ? "s" : ""}
                </span>
                <button onClick={copyResultsAsTSV} style={{
    background: "none",
    border: "none",
    cursor: "pointer",
    color: mutedColor,
    fontSize: "11px",
    padding: "2px 6px",
    borderRadius: "3px"
  }} onMouseEnter={e => e.target.style.color = textColor} onMouseLeave={e => e.target.style.color = mutedColor}>
                  ⧉ Copiar TSV
                </button>
              </div>}
          </div>
        </div>}
    </div>;
};

<View title="Cloud">
  Neste tutorial, você vai explorar como o ClickHouse pode ser usado para executar consultas analíticas em grandes volumes de dados.
  Você também verá como usar um dicionário para enriquecer os dados e escrever consultas com junções.

  ## Pré-requisitos

  Para este tutorial, você vai precisar de:

  * Uma [conta no ClickHouse Cloud](https://clickhouse.cloud/signUp?loc=docs-sample-datasets-nyc-taxi) (US\$ 300 em créditos gratuitos ao se cadastrar)
  * [Um serviço do ClickHouse Cloud](/pt-BR/get-started/setup/cloud#1-create-a-clickhouse-service)

  <Steps titleSize="h2">
    <Step title="Crie a tabela" id="create-a-new-table">
      O conjunto de dados usado neste tutorial é o de táxis da cidade de Nova York, que contém detalhes sobre milhões de corridas de táxi, com colunas como valor da gorjeta, pedágios, tipo de pagamento e muito mais.

      1. Selecione **SQL Console** no menu à esquerda
      2. Clique na aba **+** ao lado do ícone de início para criar uma nova consulta
      3. No editor SQL, digite a consulta abaixo e clique em **Run**:

      ```sql Expandable theme={null}
      CREATE TABLE trips
      (
          `trip_id` UInt32,
          `vendor_id` Enum8('1' = 1, '2' = 2, '3' = 3, '4' = 4, 'CMT' = 5, 'VTS' = 6, 'DDS' = 7, 'B02512' = 10, 'B02598' = 11, 'B02617' = 12, 'B02682' = 13, 'B02764' = 14, '' = 15),
          `pickup_date` Date,
          `pickup_datetime` DateTime,
          `dropoff_date` Date,
          `dropoff_datetime` DateTime,
          `store_and_fwd_flag` UInt8,
          `rate_code_id` UInt8,
          `pickup_longitude` Float64,
          `pickup_latitude` Float64,
          `dropoff_longitude` Float64,
          `dropoff_latitude` Float64,
          `passenger_count` UInt8,
          `trip_distance` Float64,
          `fare_amount` Float32,
          `extra` Float32,
          `mta_tax` Float32,
          `tip_amount` Float32,
          `tolls_amount` Float32,
          `ehail_fee` Float32,
          `improvement_surcharge` Float32,
          `total_amount` Float32,
          `payment_type` Enum8('UNK' = 0, 'CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4),
          `trip_type` UInt8,
          `pickup` FixedString(25),
          `dropoff` FixedString(25),
          `cab_type` Enum8('yellow' = 1, 'green' = 2, 'uber' = 3),
          `pickup_nyct2010_gid` Int8,
          `pickup_ctlabel` Float32,
          `pickup_borocode` Int8,
          `pickup_ct2010` String,
          `pickup_boroct2010` String,
          `pickup_cdeligibil` String,
          `pickup_ntacode` FixedString(4),
          `pickup_ntaname` String,
          `pickup_puma` UInt16,
          `dropoff_nyct2010_gid` UInt8,
          `dropoff_ctlabel` Float32,
          `dropoff_borocode` UInt8,
          `dropoff_ct2010` String,
          `dropoff_boroct2010` String,
          `dropoff_cdeligibil` String,
          `dropoff_ntacode` FixedString(4),
          `dropoff_ntaname` String,
          `dropoff_puma` UInt16
      )
      ENGINE = MergeTree
      PARTITION BY toYYYYMM(pickup_date)
      ORDER BY pickup_datetime;
      ```
    </Step>

    <Step title="Insira os dados" id="add-the-dataset">
      Agora que você criou uma tabela, adicione os dados de táxi da cidade de Nova York a partir de arquivos CSV no S3.

      O comando a seguir insere cerca de 2.000.000 de linhas na sua tabela `trips` a partir de dois arquivos diferentes no S3: `trips_1.tsv.gz` e `trips_2.tsv.gz`:

      ```sql Expandable theme={null}
      INSERT INTO trips
      SELECT * FROM s3(
          'https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/trips_{1..2}.gz',
          'TabSeparatedWithNames', "
          `trip_id` UInt32,
          `vendor_id` Enum8('1' = 1, '2' = 2, '3' = 3, '4' = 4, 'CMT' = 5, 'VTS' = 6, 'DDS' = 7, 'B02512' = 10, 'B02598' = 11, 'B02617' = 12, 'B02682' = 13, 'B02764' = 14, '' = 15),
          `pickup_date` Date,
          `pickup_datetime` DateTime,
          `dropoff_date` Date,
          `dropoff_datetime` DateTime,
          `store_and_fwd_flag` UInt8,
          `rate_code_id` UInt8,
          `pickup_longitude` Float64,
          `pickup_latitude` Float64,
          `dropoff_longitude` Float64,
          `dropoff_latitude` Float64,
          `passenger_count` UInt8,
          `trip_distance` Float64,
          `fare_amount` Float32,
          `extra` Float32,
          `mta_tax` Float32,
          `tip_amount` Float32,
          `tolls_amount` Float32,
          `ehail_fee` Float32,
          `improvement_surcharge` Float32,
          `total_amount` Float32,
          `payment_type` Enum8('UNK' = 0, 'CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4),
          `trip_type` UInt8,
          `pickup` FixedString(25),
          `dropoff` FixedString(25),
          `cab_type` Enum8('yellow' = 1, 'green' = 2, 'uber' = 3),
          `pickup_nyct2010_gid` Int8,
          `pickup_ctlabel` Float32,
          `pickup_borocode` Int8,
          `pickup_ct2010` String,
          `pickup_boroct2010` String,
          `pickup_cdeligibil` String,
          `pickup_ntacode` FixedString(4),
          `pickup_ntaname` String,
          `pickup_puma` UInt16,
          `dropoff_nyct2010_gid` UInt8,
          `dropoff_ctlabel` Float32,
          `dropoff_borocode` UInt8,
          `dropoff_ct2010` String,
          `dropoff_boroct2010` String,
          `dropoff_cdeligibil` String,
          `dropoff_ntacode` FixedString(4),
          `dropoff_ntaname` String,
          `dropoff_puma` UInt16
      ") SETTINGS input_format_try_infer_datetimes = 0
      ```

      Aguarde até que a inserção dos dados seja concluída. Cerca de 150 MB de dados serão baixados.
      Quando a inserção terminar, verifique o número de linhas na tabela `trips`:

      ```sql theme={null}
      SELECT count() FROM trips
      ```

      O resultado deve ter 1.999.657 linhas
    </Step>

    <Step title="Analise os dados" id="analyze-the-data">
      Com os dados carregados, você pode executar algumas consultas para analisá-los.

      * Calcule o valor médio das gorjetas:
        ```sql theme={null}
        SELECT round(avg(tip_amount), 2) FROM trips
        ```

      * Calcule o custo médio com base no número de passageiros:
        ```sql theme={null}
        SELECT
            passenger_count,
            ceil(avg(total_amount),2) AS average_total_amount
        FROM trips
        GROUP BY passenger_count
        ```

      * Calcule o número diário de embarques por bairro:
        ```sql theme={null}
        SELECT
          pickup_date,
          pickup_ntaname,
          SUM(1) AS number_of_trips
        FROM trips
        GROUP BY pickup_date, pickup_ntaname
        ORDER BY pickup_date ASC
        ```

      * Calcule a duração de cada corrida em minutos e, em seguida, agrupe os resultados por duração:
        ```sql theme={null}
        SELECT
          avg(tip_amount) AS avg_tip,
          avg(fare_amount) AS avg_fare,
          avg(passenger_count) AS avg_passenger,
          count() AS count,
          truncate(date_diff('second', pickup_datetime, dropoff_datetime)/60) as trip_minutes
        FROM trips
        WHERE trip_minutes > 0
        GROUP BY trip_minutes
        ORDER BY trip_minutes DESC
        ```

      * Mostre o número de embarques em cada bairro, discriminado por hora do dia:
        ```sql theme={null}
        SELECT
            pickup_ntaname,
            toHour(pickup_datetime) as pickup_hour,
            SUM(1) AS pickups
        FROM trips
        WHERE pickup_ntaname != ''
        GROUP BY pickup_ntaname, pickup_hour
        ORDER BY pickup_ntaname, pickup_hour
        ```
    </Step>

    <Step title="Criar um dicionário" id="create-a-dictionary">
      Em seguida, você criará um dicionário (um mapeamento de pares chave-valor armazenado em memória) chamado `taxi_zone_dictionary` para mapear IDs de localização para nomes de distritos (boroughs) de NYC, com base em um arquivo CSV que contém todos os bairros da cidade de Nova York.
      Esses IDs correspondem às colunas `pickup_nyct2010_gid` e `dropoff_nyct2010_gid` na tabela de corridas.

      Veja abaixo um trecho do arquivo CSV que você está usando, em formato de tabela. A coluna `LocationID` do arquivo corresponde às colunas `pickup_nyct2010_gid` e `dropoff_nyct2010_gid` da sua tabela `trips`:

      | LocationID | Borough | Zone | service\_zone |
      | - | - | - | - |
      | 1 | EWR | Newark Airport | EWR |
      | 2 | Queens | Jamaica Bay | Boro Zone |
      | 3 | Bronx | Allerton/Pelham Gardens | Boro Zone |
      | 4 | Manhattan | Alphabet City | Yellow Zone |
      | 5 | Staten Island | Arden Heights | Boro Zone |

      Execute o comando SQL a seguir, que cria um dicionário chamado `taxi_zone_dictionary` e o preenche com os dados do arquivo CSV no S3. A URL do arquivo é `https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/taxi_zone_lookup.csv`.

      ```sql theme={null}
      CREATE DICTIONARY taxi_zone_dictionary
      (
        `LocationID` UInt16 DEFAULT 0,
        `Borough` String,
        `Zone` String,
        `service_zone` String
      )
      PRIMARY KEY LocationID
      SOURCE(HTTP(URL 'https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/taxi_zone_lookup.csv' FORMAT 'CSVWithNames'))
      LIFETIME(MIN 0 MAX 0)
      LAYOUT(HASHED_ARRAY())
      ```

      <Note>
        Definir `LIFETIME` como 0 desabilita as atualizações automáticas, evitando tráfego desnecessário para o nosso bucket do S3. Em outros cenários, talvez seja conveniente configurá-lo de outra forma. Para mais detalhes, consulte [Atualização de dados de dicionário usando LIFETIME](/pt-BR/reference/statements/create/dictionary/lifetime).
      </Note>

      Verifique se funcionou. A consulta a seguir deve retornar 265 linhas, ou seja, uma linha para cada bairro:

      ```sql theme={null}
      SELECT * FROM taxi_zone_dictionary
      ```
    </Step>

    <Step title="Execute consultas usando o dicionário">
      Você pode usar a função `dictGet` ([ou suas variações](/pt-BR/reference/functions/regular-functions/ext-dict-functions)) para obter um valor de um dicionário.
      Basta informar o nome do dicionário, o valor desejado e a chave (que, no nosso exemplo, é a coluna `LocationID` de `taxi_zone_dictionary`) para receber o valor correspondente.
      Por exemplo, a consulta a seguir retorna o `Borough` cujo `LocationID` é 132 (que corresponde ao aeroporto JFK):

      ```sql theme={null}
      SELECT dictGet('taxi_zone_dictionary', 'Borough', 132)
      ```

      O JFK fica no Queens. Observe que o tempo para recuperar o valor é praticamente zero:

      ```response theme={null}
      ┌─dictGet('taxi_zone_dictionary', 'Borough', 132)─┐
      │ Queens                                          │
      └─────────────────────────────────────────────────┘

      1 rows in set. Elapsed: 0.004 sec.
      ```

      Use a função `dictHas` para verificar se uma chave existe no dicionário. Por exemplo, a consulta a seguir retorna `1` (que equivale a "true" no ClickHouse):

      ```sql theme={null}
      SELECT dictHas('taxi_zone_dictionary', 132)
      ```

      A consulta a seguir retorna 0 porque 4567 não é um valor de `LocationID` no dicionário:

      ```sql theme={null}
      SELECT dictHas('taxi_zone_dictionary', 4567)
      ```

      Use a função `dictGet` para obter o nome de um distrito em uma consulta. Por exemplo:

      ```sql theme={null}
      SELECT
        count(1) AS total,
        dictGetOrDefault('taxi_zone_dictionary','Borough', toUInt64(pickup_nyct2010_gid), 'Unknown') AS borough_name
      FROM trips
      WHERE dropoff_nyct2010_gid = 132 OR dropoff_nyct2010_gid = 138
      GROUP BY borough_name
      ORDER BY total DESC
      ```

      Esta consulta soma o número de corridas de táxi por distrito que terminam no aeroporto LaGuardia ou no JFK. O resultado é semelhante ao seguinte. Observe que há muitas corridas em que o bairro de embarque é desconhecido:

      ```response theme={null}
      ┌─total─┬─borough_name──┐
      │ 23683 │ Unknown       │
      │  7053 │ Manhattan     │
      │  6828 │ Brooklyn      │
      │  4458 │ Queens        │
      │  2670 │ Bronx         │
      │   554 │ Staten Island │
      │    53 │ EWR           │
      └───────┴───────────────┘

      7 rows in set. Elapsed: 0.019 sec. Processed 2.00 million rows, 4.00 MB (105.70 million rows/s., 211.40 MB/s.)
      ```
    </Step>

    <Step title="Faça uma junção" id="perform-a-join">
      Por fim, escreva algumas consultas que façam a junção do `taxi_zone_dictionary` com a sua tabela `trips`.

      Comece com um `JOIN` simples que funcione de forma semelhante à consulta sobre aeroportos mostrada anteriormente:

      ```sql theme={null}
      SELECT
          count(1) AS total,
          Borough
      FROM trips
      JOIN taxi_zone_dictionary ON toUInt64(trips.pickup_nyct2010_gid) = taxi_zone_dictionary.LocationID
      WHERE dropoff_nyct2010_gid = 132 OR dropoff_nyct2010_gid = 138
      GROUP BY Borough
      ORDER BY total DESC
      ```

      A resposta é idêntica à da consulta com `dictGet`:

      ```response theme={null}
      ┌─total─┬─Borough───────┐
      │  7053 │ Manhattan     │
      │  6828 │ Brooklyn      │
      │  4458 │ Queens        │
      │  2670 │ Bronx         │
      │   554 │ Staten Island │
      │    53 │ EWR           │
      └───────┴───────────────┘

      6 rows in set. Elapsed: 0.034 sec. Processed 2.00 million rows, 4.00 MB (59.14 million rows/s., 118.29 MB/s.)
      ```

      <Note>
        Observe que o resultado da consulta `JOIN` acima é o mesmo da consulta anterior, que usava `dictGetOrDefault` (exceto pelo fato de que os valores `Unknown` não são incluídos).
        Nos bastidores, o ClickHouse está, na verdade, chamando a função `dictGet` para o dicionário `taxi_zone_dictionary`, mas a sintaxe `JOIN` é mais familiar para desenvolvedores SQL.
      </Note>

      Esta consulta retorna as linhas das 1000 corridas com os maiores valores de gorjeta e, em seguida, realiza uma junção interna de cada linha com o dicionário:

      ```sql theme={null}
      SELECT *
      FROM trips
      JOIN taxi_zone_dictionary
      ON trips.dropoff_nyct2010_gid = taxi_zone_dictionary.LocationID
      WHERE tip_amount > 0
      ORDER BY tip_amount DESC
      LIMIT 1000
      ```

      <Tip>
        Prefira listar apenas as colunas de que sua consulta precisa, em vez de usar SELECT \*. Como o ClickHouse armazena os dados por coluna, selecionar menos colunas reduz diretamente o volume de dados lidos, descomprimidos e processados.
      </Tip>
    </Step>
  </Steps>

  ## Próximos passos

  Saiba mais sobre o ClickHouse na documentação a seguir:

  * [Introdução aos índices primários no ClickHouse](/pt-BR/guides/clickhouse/data-modelling/sparse-primary-indexes): Saiba como o ClickHouse usa índices primários esparsos para localizar com eficiência os dados relevantes durante as consultas.
  * [Integre uma fonte de dados externa](/pt-BR/integrations/home): Conheça as opções de integração de fontes de dados, incluindo arquivos, Kafka, PostgreSQL, pipelines de dados e muitas outras.
  * [Visualize dados no ClickHouse](/pt-BR/integrations/connectors/data-visualization/index): Conecte sua ferramenta de UI/BI preferida ao ClickHouse.
  * [Referência SQL](/pt-BR/reference/home): Explore as funções SQL disponíveis no ClickHouse para transformar, processar e analisar dados.
</View>

<View title="Código aberto">
  A amostra de dados de táxi de Nova York reúne mais de 3 bilhões de viagens de táxi e de veículos de aluguel com motorista (Uber, Lyft etc.) iniciadas na cidade de Nova York desde 2009. Este guia de primeiros passos usa uma amostra de 3 milhões de linhas.

  O conjunto de dados completo pode ser obtido de duas maneiras:

  * inserir os dados diretamente no ClickHouse Cloud a partir do S3 ou do GCS
  * baixar partições preparadas
  * Como alternativa, você pode consultar o conjunto de dados completo em nosso ambiente de demonstração em [sql.clickhouse.com](https://sql.clickhouse.com/?query=U0VMRUNUIGNvdW50KCkgRlJPTSBueWNfdGF4aS50cmlwcw\&chart=eyJ0eXBlIjoibGluZSIsImNvbmZpZyI6eyJ0aXRsZSI6IlRlbXBlcmF0dXJlIGJ5IGNvdW50cnkgYW5kIHllYXIiLCJ4YXhpcyI6InllYXIiLCJ5YXhpcyI6ImNvdW50KCkiLCJzZXJpZXMiOiJDQVNUKHBhc3Nlbmdlcl9jb3VudCwgJ1N0cmluZycpIn19).

  <Note>
    As consultas de exemplo abaixo foram executadas em uma instância **Production** do ClickHouse Cloud. Para mais informações, consulte
    ["Especificações do Playground"](/pt-BR/get-started/sample-datasets/playground#specifications).
  </Note>

  ## Criar a tabela trips

  Comece criando uma tabela para as corridas de táxi:

  ```sql theme={null}

  CREATE DATABASE nyc_taxi;

  CREATE TABLE nyc_taxi.trips_small (
      trip_id             UInt32,
      pickup_datetime     DateTime,
      dropoff_datetime    DateTime,
      pickup_longitude    Nullable(Float64),
      pickup_latitude     Nullable(Float64),
      dropoff_longitude   Nullable(Float64),
      dropoff_latitude    Nullable(Float64),
      passenger_count     UInt8,
      trip_distance       Float32,
      fare_amount         Float32,
      extra               Float32,
      tip_amount          Float32,
      tolls_amount        Float32,
      total_amount        Float32,
      payment_type        Enum('CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4, 'UNK' = 5),
      pickup_ntaname      LowCardinality(String),
      dropoff_ntaname     LowCardinality(String)
  )
  ENGINE = MergeTree
  PRIMARY KEY (pickup_datetime, dropoff_datetime);
  ```

  ## Carregue os dados diretamente do armazenamento de objetos

  Os usuários podem obter um pequeno subconjunto dos dados (3 milhões de linhas) para se familiarizar com eles. Os dados estão em arquivos TSV no armazenamento de objetos, de onde podem ser facilmente transmitidos para o
  ClickHouse Cloud usando a função de tabela `s3`.

  Os mesmos dados estão armazenados no S3 e no GCS; escolha qualquer uma das abas.

  <Tabs>
    <Tab title="S3">
      O comando a seguir transfere, via streaming, três arquivos de um bucket do S3 para a tabela `trips_small` (a sintaxe `{0..2}` é um wildcard para os valores 0, 1 e 2):

      ```sql theme={null}
      INSERT INTO nyc_taxi.trips_small
      SELECT
          trip_id,
          pickup_datetime,
          dropoff_datetime,
          pickup_longitude,
          pickup_latitude,
          dropoff_longitude,
          dropoff_latitude,
          passenger_count,
          trip_distance,
          fare_amount,
          extra,
          tip_amount,
          tolls_amount,
          total_amount,
          payment_type,
          pickup_ntaname,
          dropoff_ntaname
      FROM s3(
          'https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/trips_{0..2}.gz',
          'TabSeparatedWithNames'
      );
      ```
    </Tab>

    <Tab title="GCS">
      O comando a seguir transfere, via streaming, três arquivos de um bucket do GCS para a tabela `trips` (a sintaxe `{0..2}` é um wildcard para os valores 0, 1 e 2):

      ```sql theme={null}
      INSERT INTO nyc_taxi.trips_small
      SELECT
          trip_id,
          pickup_datetime,
          dropoff_datetime,
          pickup_longitude,
          pickup_latitude,
          dropoff_longitude,
          dropoff_latitude,
          passenger_count,
          trip_distance,
          fare_amount,
          extra,
          tip_amount,
          tolls_amount,
          total_amount,
          payment_type,
          pickup_ntaname,
          dropoff_ntaname
      FROM gcs(
          'https://storage.googleapis.com/clickhouse-public-datasets/nyc-taxi/trips_{0..2}.gz',
          'TabSeparatedWithNames'
      );
      ```
    </Tab>
  </Tabs>

  ## Consultas de exemplo

  As consultas a seguir são executadas na amostra descrita acima. Você pode executar as consultas de exemplo no conjunto de dados completo em [sql.clickhouse.com](https://sql.clickhouse.com/?query=U0VMRUNUIGNvdW50KCkgRlJPTSBueWNfdGF4aS50cmlwcw\&chart=eyJ0eXBlIjoibGluZSIsImNvbmZpZyI6eyJ0aXRsZSI6IlRlbXBlcmF0dXJlIGJ5IGNvdW50cnkgYW5kIHllYXIiLCJ4YXhpcyI6InllYXIiLCJ5YXhpcyI6ImNvdW50KCkiLCJzZXJpZXMiOiJDQVNUKHBhc3Nlbmdlcl9jb3VudCwgJ1N0cmluZycpIn19), modificando as consultas abaixo para usar a tabela `nyc_taxi.trips`.

  Vamos ver quantas linhas foram inseridas:

  <RunnableCode>
    ```sql theme={null}
    SELECT count()
    FROM nyc_taxi.trips_small;
    ```
  </RunnableCode>

  Cada arquivo TSV tem cerca de 1 milhão de linhas, e os três arquivos têm 3.000.317 linhas. Vamos ver algumas delas:

  <RunnableCode>
    ```sql theme={null}
    SELECT *
    FROM nyc_taxi.trips_small
    LIMIT 10;
    ```
  </RunnableCode>

  Observe que há colunas para as datas de embarque e desembarque, coordenadas geográficas, detalhes da tarifa, bairros de Nova York e muito mais.

  Vamos executar algumas consultas. Esta consulta mostra os 10 bairros com maior frequência de embarques:

  <RunnableCode>
    ```sql theme={null}
    SELECT
       pickup_ntaname,
       count(*) AS count
    FROM nyc_taxi.trips_small WHERE pickup_ntaname != ''
    GROUP BY pickup_ntaname
    ORDER BY count DESC
    LIMIT 10;
    ```
  </RunnableCode>

  Esta consulta mostra a tarifa média com base no número de passageiros:

  ```sql runnable view='chart' chart_config='eyJ0eXBlIjoiYmFyIiwiY29uZmlnIjp7InhheGlzIjoicGFzc2VuZ2VyX2NvdW50IiwieWF4aXMiOiJhdmcodG90YWxfYW1vdW50KSIsInRpdGxlIjoiQXZlcmFnZSBmYXJlIGJ5IHBhc3NlbmdlciBjb3VudCJ9fQ' theme={null}
  SELECT
     passenger_count,
     avg(total_amount)
  FROM nyc_taxi.trips_small
  WHERE passenger_count < 10
  GROUP BY passenger_count;
  ```

  Veja a correlação entre o número de passageiros e a distância da viagem:

  ```sql runnable chart_config='eyJ0eXBlIjoiaG9yaXpvbnRhbCBiYXIiLCJjb25maWciOnsieGF4aXMiOiJwYXNzZW5nZXJfY291bnQiLCJ5YXhpcyI6ImRpc3RhbmNlIiwic2VyaWVzIjoiY291bnRyeSIsInRpdGxlIjoiQXZnIGZhcmUgYnkgcGFzc2VuZ2VyIGNvdW50In19' theme={null}
  SELECT
      passenger_count,
      avg(trip_distance) AS distance,
      count() AS c
  FROM nyc_taxi.trips_small
  GROUP BY passenger_count
  ORDER BY passenger_count ASC
  ```

  ## Download das partições preparadas

  <Note>
    As etapas a seguir apresentam informações sobre o conjunto de dados original e um método para carregar partições preparadas em um ambiente com servidor ClickHouse autogerenciado.
  </Note>

  Consulte [https://github.com/toddwschneider/nyc-taxi-data](https://github.com/toddwschneider/nyc-taxi-data) e [http://tech.marksblogg.com/billion-nyc-taxi-rides-redshift.html](http://tech.marksblogg.com/billion-nyc-taxi-rides-redshift.html) para ver a descrição do conjunto de dados e as instruções de download.

  O download resultará em cerca de 227 GB de dados não comprimidos em arquivos CSV. O download leva cerca de uma hora em uma conexão de 1 Gbit (o download paralelo a partir de s3.amazonaws.com aproveita pelo menos metade de um canal de 1 Gbit).
  Alguns arquivos podem não ser baixados por completo. Verifique o tamanho dos arquivos e baixe novamente aqueles que parecerem suspeitos.

  ```bash theme={null}
  $ curl -O https://datasets.clickhouse.com/trips_mergetree/partitions/trips_mergetree.tar
  # Validate the checksum
  $ md5sum trips_mergetree.tar
  # Checksum should be equal to: f3b8d469b41d9a82da064ded7245d12c
  $ tar xvf trips_mergetree.tar -C /var/lib/clickhouse # path to ClickHouse data directory
  $ # check permissions of unpacked data, fix if required
  $ sudo service clickhouse-server restart
  $ clickhouse-client --query "select count(*) from datasets.trips_mergetree"
  ```

  <Info>
    Se você for executar as consultas descritas abaixo, precisará usar o nome completo da tabela, `datasets.trips_mergetree`.
  </Info>

  ## Resultados em um único servidor

  Q1:

  ```sql theme={null}
  SELECT cab_type, count(*) FROM trips_mergetree GROUP BY cab_type;
  ```

  0,490 segundos.

  Q2:

  ```sql theme={null}
  SELECT passenger_count, avg(total_amount) FROM trips_mergetree GROUP BY passenger_count;
  ```

  1,224 segundos.

  Q3:

  ```sql theme={null}
  SELECT passenger_count, toYear(pickup_date) AS year, count(*) FROM trips_mergetree GROUP BY passenger_count, year;
  ```

  2,104 segundos.

  Q4:

  ```sql theme={null}
  SELECT passenger_count, toYear(pickup_date) AS year, round(trip_distance) AS distance, count(*)
  FROM trips_mergetree
  GROUP BY passenger_count, year, distance
  ORDER BY year, count(*) DESC;
  ```

  3,593 segundos.

  Foi utilizado o seguinte servidor:

  Duas CPUs Intel(R) Xeon(R) E5-2650 v2 @ 2.60GHz, 16 núcleos físicos no total, 128 GiB de RAM, 8 HDs de 6 TB em RAID-5 por hardware

  O tempo de execução corresponde ao melhor resultado de três execuções. Porém, a partir da segunda execução, as consultas leem os dados do cache do sistema de arquivos. Nenhum outro cache é utilizado: os dados são lidos e processados em cada execução.

  Criando uma tabela em três servidores:

  Em cada servidor:

  ```sql theme={null}
  CREATE TABLE default.trips_mergetree_third ( trip_id UInt32,  vendor_id Enum8('1' = 1, '2' = 2, 'CMT' = 3, 'VTS' = 4, 'DDS' = 5, 'B02512' = 10, 'B02598' = 11, 'B02617' = 12, 'B02682' = 13, 'B02764' = 14),  pickup_date Date,  pickup_datetime DateTime,  dropoff_date Date,  dropoff_datetime DateTime,  store_and_fwd_flag UInt8,  rate_code_id UInt8,  pickup_longitude Float64,  pickup_latitude Float64,  dropoff_longitude Float64,  dropoff_latitude Float64,  passenger_count UInt8,  trip_distance Float64,  fare_amount Float32,  extra Float32,  mta_tax Float32,  tip_amount Float32,  tolls_amount Float32,  ehail_fee Float32,  improvement_surcharge Float32,  total_amount Float32,  payment_type_ Enum8('UNK' = 0, 'CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4),  trip_type UInt8,  pickup FixedString(25),  dropoff FixedString(25),  cab_type Enum8('yellow' = 1, 'green' = 2, 'uber' = 3),  pickup_nyct2010_gid UInt8,  pickup_ctlabel Float32,  pickup_borocode UInt8,  pickup_boroname Enum8('' = 0, 'Manhattan' = 1, 'Bronx' = 2, 'Brooklyn' = 3, 'Queens' = 4, 'Staten Island' = 5),  pickup_ct2010 FixedString(6),  pickup_boroct2010 FixedString(7),  pickup_cdeligibil Enum8(' ' = 0, 'E' = 1, 'I' = 2),  pickup_ntacode FixedString(4),  pickup_ntaname Enum16('' = 0, 'Airport' = 1, 'Allerton-Pelham Gardens' = 2, 'Annadale-Huguenot-Prince\'s Bay-Eltingville' = 3, 'Arden Heights' = 4, 'Astoria' = 5, 'Auburndale' = 6, 'Baisley Park' = 7, 'Bath Beach' = 8, 'Battery Park City-Lower Manhattan' = 9, 'Bay Ridge' = 10, 'Bayside-Bayside Hills' = 11, 'Bedford' = 12, 'Bedford Park-Fordham North' = 13, 'Bellerose' = 14, 'Belmont' = 15, 'Bensonhurst East' = 16, 'Bensonhurst West' = 17, 'Borough Park' = 18, 'Breezy Point-Belle Harbor-Rockaway Park-Broad Channel' = 19, 'Briarwood-Jamaica Hills' = 20, 'Brighton Beach' = 21, 'Bronxdale' = 22, 'Brooklyn Heights-Cobble Hill' = 23, 'Brownsville' = 24, 'Bushwick North' = 25, 'Bushwick South' = 26, 'Cambria Heights' = 27, 'Canarsie' = 28, 'Carroll Gardens-Columbia Street-Red Hook' = 29, 'Central Harlem North-Polo Grounds' = 30, 'Central Harlem South' = 31, 'Charleston-Richmond Valley-Tottenville' = 32, 'Chinatown' = 33, 'Claremont-Bathgate' = 34, 'Clinton' = 35, 'Clinton Hill' = 36, 'Co-op City' = 37, 'College Point' = 38, 'Corona' = 39, 'Crotona Park East' = 40, 'Crown Heights North' = 41, 'Crown Heights South' = 42, 'Cypress Hills-City Line' = 43, 'DUMBO-Vinegar Hill-Downtown Brooklyn-Boerum Hill' = 44, 'Douglas Manor-Douglaston-Little Neck' = 45, 'Dyker Heights' = 46, 'East Concourse-Concourse Village' = 47, 'East Elmhurst' = 48, 'East Flatbush-Farragut' = 49, 'East Flushing' = 50, 'East Harlem North' = 51, 'East Harlem South' = 52, 'East New York' = 53, 'East New York (Pennsylvania Ave)' = 54, 'East Tremont' = 55, 'East Village' = 56, 'East Williamsburg' = 57, 'Eastchester-Edenwald-Baychester' = 58, 'Elmhurst' = 59, 'Elmhurst-Maspeth' = 60, 'Erasmus' = 61, 'Far Rockaway-Bayswater' = 62, 'Flatbush' = 63, 'Flatlands' = 64, 'Flushing' = 65, 'Fordham South' = 66, 'Forest Hills' = 67, 'Fort Greene' = 68, 'Fresh Meadows-Utopia' = 69, 'Ft. Totten-Bay Terrace-Clearview' = 70, 'Georgetown-Marine Park-Bergen Beach-Mill Basin' = 71, 'Glen Oaks-Floral Park-New Hyde Park' = 72, 'Glendale' = 73, 'Gramercy' = 74, 'Grasmere-Arrochar-Ft. Wadsworth' = 75, 'Gravesend' = 76, 'Great Kills' = 77, 'Greenpoint' = 78, 'Grymes Hill-Clifton-Fox Hills' = 79, 'Hamilton Heights' = 80, 'Hammels-Arverne-Edgemere' = 81, 'Highbridge' = 82, 'Hollis' = 83, 'Homecrest' = 84, 'Hudson Yards-Chelsea-Flatiron-Union Square' = 85, 'Hunters Point-Sunnyside-West Maspeth' = 86, 'Hunts Point' = 87, 'Jackson Heights' = 88, 'Jamaica' = 89, 'Jamaica Estates-Holliswood' = 90, 'Kensington-Ocean Parkway' = 91, 'Kew Gardens' = 92, 'Kew Gardens Hills' = 93, 'Kingsbridge Heights' = 94, 'Laurelton' = 95, 'Lenox Hill-Roosevelt Island' = 96, 'Lincoln Square' = 97, 'Lindenwood-Howard Beach' = 98, 'Longwood' = 99, 'Lower East Side' = 100, 'Madison' = 101, 'Manhattanville' = 102, 'Marble Hill-Inwood' = 103, 'Mariner\'s Harbor-Arlington-Port Ivory-Graniteville' = 104, 'Maspeth' = 105, 'Melrose South-Mott Haven North' = 106, 'Middle Village' = 107, 'Midtown-Midtown South' = 108, 'Midwood' = 109, 'Morningside Heights' = 110, 'Morrisania-Melrose' = 111, 'Mott Haven-Port Morris' = 112, 'Mount Hope' = 113, 'Murray Hill' = 114, 'Murray Hill-Kips Bay' = 115, 'New Brighton-Silver Lake' = 116, 'New Dorp-Midland Beach' = 117, 'New Springville-Bloomfield-Travis' = 118, 'North Corona' = 119, 'North Riverdale-Fieldston-Riverdale' = 120, 'North Side-South Side' = 121, 'Norwood' = 122, 'Oakland Gardens' = 123, 'Oakwood-Oakwood Beach' = 124, 'Ocean Hill' = 125, 'Ocean Parkway South' = 126, 'Old Astoria' = 127, 'Old Town-Dongan Hills-South Beach' = 128, 'Ozone Park' = 129, 'Park Slope-Gowanus' = 130, 'Parkchester' = 131, 'Pelham Bay-Country Club-City Island' = 132, 'Pelham Parkway' = 133, 'Pomonok-Flushing Heights-Hillcrest' = 134, 'Port Richmond' = 135, 'Prospect Heights' = 136, 'Prospect Lefferts Gardens-Wingate' = 137, 'Queens Village' = 138, 'Queensboro Hill' = 139, 'Queensbridge-Ravenswood-Long Island City' = 140, 'Rego Park' = 141, 'Richmond Hill' = 142, 'Ridgewood' = 143, 'Rikers Island' = 144, 'Rosedale' = 145, 'Rossville-Woodrow' = 146, 'Rugby-Remsen Village' = 147, 'Schuylerville-Throgs Neck-Edgewater Park' = 148, 'Seagate-Coney Island' = 149, 'Sheepshead Bay-Gerritsen Beach-Manhattan Beach' = 150, 'SoHo-TriBeCa-Civic Center-Little Italy' = 151, 'Soundview-Bruckner' = 152, 'Soundview-Castle Hill-Clason Point-Harding Park' = 153, 'South Jamaica' = 154, 'South Ozone Park' = 155, 'Springfield Gardens North' = 156, 'Springfield Gardens South-Brookville' = 157, 'Spuyten Duyvil-Kingsbridge' = 158, 'St. Albans' = 159, 'Stapleton-Rosebank' = 160, 'Starrett City' = 161, 'Steinway' = 162, 'Stuyvesant Heights' = 163, 'Stuyvesant Town-Cooper Village' = 164, 'Sunset Park East' = 165, 'Sunset Park West' = 166, 'Todt Hill-Emerson Hill-Heartland Village-Lighthouse Hill' = 167, 'Turtle Bay-East Midtown' = 168, 'University Heights-Morris Heights' = 169, 'Upper East Side-Carnegie Hill' = 170, 'Upper West Side' = 171, 'Van Cortlandt Village' = 172, 'Van Nest-Morris Park-Westchester Square' = 173, 'Washington Heights North' = 174, 'Washington Heights South' = 175, 'West Brighton' = 176, 'West Concourse' = 177, 'West Farms-Bronx River' = 178, 'West New Brighton-New Brighton-St. George' = 179, 'West Village' = 180, 'Westchester-Unionport' = 181, 'Westerleigh' = 182, 'Whitestone' = 183, 'Williamsbridge-Olinville' = 184, 'Williamsburg' = 185, 'Windsor Terrace' = 186, 'Woodhaven' = 187, 'Woodlawn-Wakefield' = 188, 'Woodside' = 189, 'Yorkville' = 190, 'park-cemetery-etc-Bronx' = 191, 'park-cemetery-etc-Brooklyn' = 192, 'park-cemetery-etc-Manhattan' = 193, 'park-cemetery-etc-Queens' = 194, 'park-cemetery-etc-Staten Island' = 195),  pickup_puma UInt16,  dropoff_nyct2010_gid UInt8,  dropoff_ctlabel Float32,  dropoff_borocode UInt8,  dropoff_boroname Enum8('' = 0, 'Manhattan' = 1, 'Bronx' = 2, 'Brooklyn' = 3, 'Queens' = 4, 'Staten Island' = 5),  dropoff_ct2010 FixedString(6),  dropoff_boroct2010 FixedString(7),  dropoff_cdeligibil Enum8(' ' = 0, 'E' = 1, 'I' = 2),  dropoff_ntacode FixedString(4),  dropoff_ntaname Enum16('' = 0, 'Airport' = 1, 'Allerton-Pelham Gardens' = 2, 'Annadale-Huguenot-Prince\'s Bay-Eltingville' = 3, 'Arden Heights' = 4, 'Astoria' = 5, 'Auburndale' = 6, 'Baisley Park' = 7, 'Bath Beach' = 8, 'Battery Park City-Lower Manhattan' = 9, 'Bay Ridge' = 10, 'Bayside-Bayside Hills' = 11, 'Bedford' = 12, 'Bedford Park-Fordham North' = 13, 'Bellerose' = 14, 'Belmont' = 15, 'Bensonhurst East' = 16, 'Bensonhurst West' = 17, 'Borough Park' = 18, 'Breezy Point-Belle Harbor-Rockaway Park-Broad Channel' = 19, 'Briarwood-Jamaica Hills' = 20, 'Brighton Beach' = 21, 'Bronxdale' = 22, 'Brooklyn Heights-Cobble Hill' = 23, 'Brownsville' = 24, 'Bushwick North' = 25, 'Bushwick South' = 26, 'Cambria Heights' = 27, 'Canarsie' = 28, 'Carroll Gardens-Columbia Street-Red Hook' = 29, 'Central Harlem North-Polo Grounds' = 30, 'Central Harlem South' = 31, 'Charleston-Richmond Valley-Tottenville' = 32, 'Chinatown' = 33, 'Claremont-Bathgate' = 34, 'Clinton' = 35, 'Clinton Hill' = 36, 'Co-op City' = 37, 'College Point' = 38, 'Corona' = 39, 'Crotona Park East' = 40, 'Crown Heights North' = 41, 'Crown Heights South' = 42, 'Cypress Hills-City Line' = 43, 'DUMBO-Vinegar Hill-Downtown Brooklyn-Boerum Hill' = 44, 'Douglas Manor-Douglaston-Little Neck' = 45, 'Dyker Heights' = 46, 'East Concourse-Concourse Village' = 47, 'East Elmhurst' = 48, 'East Flatbush-Farragut' = 49, 'East Flushing' = 50, 'East Harlem North' = 51, 'East Harlem South' = 52, 'East New York' = 53, 'East New York (Pennsylvania Ave)' = 54, 'East Tremont' = 55, 'East Village' = 56, 'East Williamsburg' = 57, 'Eastchester-Edenwald-Baychester' = 58, 'Elmhurst' = 59, 'Elmhurst-Maspeth' = 60, 'Erasmus' = 61, 'Far Rockaway-Bayswater' = 62, 'Flatbush' = 63, 'Flatlands' = 64, 'Flushing' = 65, 'Fordham South' = 66, 'Forest Hills' = 67, 'Fort Greene' = 68, 'Fresh Meadows-Utopia' = 69, 'Ft. Totten-Bay Terrace-Clearview' = 70, 'Georgetown-Marine Park-Bergen Beach-Mill Basin' = 71, 'Glen Oaks-Floral Park-New Hyde Park' = 72, 'Glendale' = 73, 'Gramercy' = 74, 'Grasmere-Arrochar-Ft. Wadsworth' = 75, 'Gravesend' = 76, 'Great Kills' = 77, 'Greenpoint' = 78, 'Grymes Hill-Clifton-Fox Hills' = 79, 'Hamilton Heights' = 80, 'Hammels-Arverne-Edgemere' = 81, 'Highbridge' = 82, 'Hollis' = 83, 'Homecrest' = 84, 'Hudson Yards-Chelsea-Flatiron-Union Square' = 85, 'Hunters Point-Sunnyside-West Maspeth' = 86, 'Hunts Point' = 87, 'Jackson Heights' = 88, 'Jamaica' = 89, 'Jamaica Estates-Holliswood' = 90, 'Kensington-Ocean Parkway' = 91, 'Kew Gardens' = 92, 'Kew Gardens Hills' = 93, 'Kingsbridge Heights' = 94, 'Laurelton' = 95, 'Lenox Hill-Roosevelt Island' = 96, 'Lincoln Square' = 97, 'Lindenwood-Howard Beach' = 98, 'Longwood' = 99, 'Lower East Side' = 100, 'Madison' = 101, 'Manhattanville' = 102, 'Marble Hill-Inwood' = 103, 'Mariner\'s Harbor-Arlington-Port Ivory-Graniteville' = 104, 'Maspeth' = 105, 'Melrose South-Mott Haven North' = 106, 'Middle Village' = 107, 'Midtown-Midtown South' = 108, 'Midwood' = 109, 'Morningside Heights' = 110, 'Morrisania-Melrose' = 111, 'Mott Haven-Port Morris' = 112, 'Mount Hope' = 113, 'Murray Hill' = 114, 'Murray Hill-Kips Bay' = 115, 'New Brighton-Silver Lake' = 116, 'New Dorp-Midland Beach' = 117, 'New Springville-Bloomfield-Travis' = 118, 'North Corona' = 119, 'North Riverdale-Fieldston-Riverdale' = 120, 'North Side-South Side' = 121, 'Norwood' = 122, 'Oakland Gardens' = 123, 'Oakwood-Oakwood Beach' = 124, 'Ocean Hill' = 125, 'Ocean Parkway South' = 126, 'Old Astoria' = 127, 'Old Town-Dongan Hills-South Beach' = 128, 'Ozone Park' = 129, 'Park Slope-Gowanus' = 130, 'Parkchester' = 131, 'Pelham Bay-Country Club-City Island' = 132, 'Pelham Parkway' = 133, 'Pomonok-Flushing Heights-Hillcrest' = 134, 'Port Richmond' = 135, 'Prospect Heights' = 136, 'Prospect Lefferts Gardens-Wingate' = 137, 'Queens Village' = 138, 'Queensboro Hill' = 139, 'Queensbridge-Ravenswood-Long Island City' = 140, 'Rego Park' = 141, 'Richmond Hill' = 142, 'Ridgewood' = 143, 'Rikers Island' = 144, 'Rosedale' = 145, 'Rossville-Woodrow' = 146, 'Rugby-Remsen Village' = 147, 'Schuylerville-Throgs Neck-Edgewater Park' = 148, 'Seagate-Coney Island' = 149, 'Sheepshead Bay-Gerritsen Beach-Manhattan Beach' = 150, 'SoHo-TriBeCa-Civic Center-Little Italy' = 151, 'Soundview-Bruckner' = 152, 'Soundview-Castle Hill-Clason Point-Harding Park' = 153, 'South Jamaica' = 154, 'South Ozone Park' = 155, 'Springfield Gardens North' = 156, 'Springfield Gardens South-Brookville' = 157, 'Spuyten Duyvil-Kingsbridge' = 158, 'St. Albans' = 159, 'Stapleton-Rosebank' = 160, 'Starrett City' = 161, 'Steinway' = 162, 'Stuyvesant Heights' = 163, 'Stuyvesant Town-Cooper Village' = 164, 'Sunset Park East' = 165, 'Sunset Park West' = 166, 'Todt Hill-Emerson Hill-Heartland Village-Lighthouse Hill' = 167, 'Turtle Bay-East Midtown' = 168, 'University Heights-Morris Heights' = 169, 'Upper East Side-Carnegie Hill' = 170, 'Upper West Side' = 171, 'Van Cortlandt Village' = 172, 'Van Nest-Morris Park-Westchester Square' = 173, 'Washington Heights North' = 174, 'Washington Heights South' = 175, 'West Brighton' = 176, 'West Concourse' = 177, 'West Farms-Bronx River' = 178, 'West New Brighton-New Brighton-St. George' = 179, 'West Village' = 180, 'Westchester-Unionport' = 181, 'Westerleigh' = 182, 'Whitestone' = 183, 'Williamsbridge-Olinville' = 184, 'Williamsburg' = 185, 'Windsor Terrace' = 186, 'Woodhaven' = 187, 'Woodlawn-Wakefield' = 188, 'Woodside' = 189, 'Yorkville' = 190, 'park-cemetery-etc-Bronx' = 191, 'park-cemetery-etc-Brooklyn' = 192, 'park-cemetery-etc-Manhattan' = 193, 'park-cemetery-etc-Queens' = 194, 'park-cemetery-etc-Staten Island' = 195),  dropoff_puma UInt16) ENGINE = MergeTree(pickup_date, pickup_datetime, 8192);
  ```

  No servidor de origem:

  ```sql theme={null}
  CREATE TABLE trips_mergetree_x3 AS trips_mergetree_third ENGINE = Distributed(perftest, default, trips_mergetree_third, rand());
  ```

  A consulta a seguir redistribui os dados:

  ```sql theme={null}
  INSERT INTO trips_mergetree_x3 SELECT * FROM trips_mergetree;
  ```

  Isso leva 2454 segundos.

  Em três servidores:

  Q1: 0,212 segundos.
  Q2: 0,438 segundos.
  Q3: 0,733 segundos.
  Q4: 1,241 segundos.

  Nada de surpreendente aqui, já que as consultas escalam linearmente.

  Também temos os resultados de um cluster de 140 servidores:

  Q1: 0.028 s
  Q2: 0.043 s
  Q3: 0.051 s
  Q4: 0.072 s

  Nesse caso, o tempo de processamento da consulta é determinado principalmente pela latência de rede.
  Executamos as consultas a partir de um cliente localizado em um datacenter diferente daquele em que o cluster estava, o que acrescentou cerca de 20 ms de latência.

  ## Resumo

  | servidores | Q1 | Q2 | Q3 | Q4 |
  | - | - | - | - | - |
  | 1, E5-2650v2 | 0.490 | 1.224 | 2.104 | 3.593 |
  | 3, E5-2650v2 | 0.212 | 0.438 | 0.733 | 1.241 |
  | 1, AWS c5n.4xlarge | 0.249 | 1.279 | 1.738 | 3.527 |
  | 1, AWS c5n.9xlarge | 0.130 | 0.584 | 0.777 | 1.811 |
  | 3, AWS c5n.9xlarge | 0.057 | 0.231 | 0.285 | 0.641 |
  | 140, E5-2650v2 | 0.028 | 0.043 | 0.051 | 0.072 |
</View>
