Mendesain tabel menggunakan Synapse SQL di Azure Synapse Analytics

Dokumen ini mencakup konsep utama untuk mendesain tabel dengan kumpulan SQL khusus dan kumpulan SQL tanpa server.

Kumpulan SQL tanpa server adalah layanan kueri atas data di data lake Anda. Ia tidak memiliki penyimpanan lokal untuk penyerapan data. Kumpulan SQL khusus mewakili kumpulan sumber daya analitik yang disediakan saat menggunakan Synapse SQL. Ukuran kumpulan SQL khusus ditentukan oleh Data Warehousing Units (DWU).

Tabel berikut mencantumkan topik yang relevan dengan kumpulan SQL khusus vs. kumpulan SQL tanpa server:

Topik kumpulan SQL khusus kumpulan SQL tanpa server
Menentukan kategori tabel Ya Tidak
Nama skema Ya Ya
Nama tabel Ya Tidak
Persistensi tabel Ya Tidak
Tabel reguler Ya Tidak
Tabel sementara Ya Ya
Tabel eksternal Ya Ya
Jenis data Ya Ya
Tabel terdistribusi Ya Tidak
Tabel terdistribusi hash Ya Tidak
Tabel yang direplikasi Ya Tidak
Tabel round-robin Ya Tidak
Metode distribusi umum untuk tabel Ya Tidak
Partisi Ya Ya
Indeks penyimpan kolom Ya Tidak
Statistik Ya Ya
Kunci primer dan kunci unik Ya Tidak
Perintah untuk membuat tabel Ya Tidak
Menyelaraskan data sumber dengan gudang data Ya Tidak
Fitur tabel yang tidak didukung Ya Tidak
Kueri ukuran tabel Ya Tidak

Menentukan kategori tabel

Skema bintang mengatur data menjadi tabel fakta dan dimensi. Beberapa tabel digunakan untuk data integrasi atau staging sebelum pindah ke tabel fakta atau dimensi. Saat Anda mendesain tabel, putuskan apakah data tabel akan berada dalam tabel fakta, dimensi, atau integrasi. Keputusan ini menginformasikan struktur dan distribusi tabel yang sesuai.

  • Tabel fakta berisi data kuantitatif yang umumnya dihasilkan dalam sistem transaksional dan kemudian dimuat ke dalam gudang data. Misalnya, setiap hari bisnis ritel menghasilkan transaksi penjualan dan kemudian memuat datanya ke dalam tabel fakta gudang data untuk keperluan analisis.

  • Tabel dimensi berisi data atribut yang mungkin berubah, tetapi biasanya jarang berubah. Misalnya, nama dan alamat pelanggan disimpan dalam tabel dimensi dan hanya diperbarui pada saat profil pelanggan berubah. Untuk mengecilkan ukuran tabel fakta yang besar, nama dan alamat pelanggan tidak perlu ada di setiap baris tabel fakta. Sebagai gantinya, tabel fakta dan tabel dimensi dapat berbagi ID pelanggan. Kueri dapat menggabungkan dua tabel untuk mengasosiasikan profil dan transaksi pelanggan.

  • Tabel integrasi menyediakan tempat untuk mengintegrasikan atau staging data. Anda bisa membuat tabel integrasi sebagai tabel reguler, tabel eksternal, atau tabel sementara. Misalnya, Anda dapat memuat data ke tabel staging, melakukan transformasi pada data dalam staging, lalu menyisipkan data ke dalam tabel produksi.

Nama skema

Skema adalah cara yang baik untuk mengelompokkan objek yang digunakan dengan cara yang sama. Kode berikut membuat skema yang ditentukan pengguna yang disebut wwi.

CREATE SCHEMA wwi;

Nama tabel

Jika Anda memigrasikan beberapa database dari solusi lokal ke kumpulan SQL khusus, praktik terbaik adalah memigrasikan semua tabel fakta, dimensi, dan integrasi ke satu skema kumpulan SQL. Misalnya, Anda dapat menyimpan semua tabel di gudang data sampel WideWorldImportersDW dalam satu skema yang disebut wwi.

Untuk menampilkan organisasi tabel di kumpulan SQL khusus, Anda dapat menggunakan fakta, dim, dan int sebagai awalan untuk nama tabel. Tabel di bawah ini memperlihatkan beberapa skema dan nama tabel untuk WideWorldImportersDW.

Tabel WideWorldImportersDW Jenis tabel kumpulan SQL khusus
Kota Dimensi wwi.DimCity
Urutan Fakta wwi.FactOrder

Persistensi tabel

Tabel menyimpan data secara permanen di Penyimpanan Azure, untuk sementara di Azure Storage atau di penyimpanan data di luar gudang data.

Tabel reguler

Tabel reguler menyimpan data di Azure Storage sebagai bagian dari gudang data. Tabel dan data akan tetap ada terlepas dari apakah sesi terbuka atau tidak. Contoh di bawah ini membuat tabel reguler dengan dua kolom.

CREATE TABLE MyTable (col1 int, col2 int );  

Tabel sementara

Tabel sementara hanya ada selama durasi sesi. Anda bisa menggunakan tabel sementara untuk mencegah pengguna lain melihat hasil sementara. Menggunakan tabel sementara juga mengurangi kebutuhan untuk pembersihan. Tabel sementara menggunakan penyimpanan lokal dan, dalam kumpulan SQL khusus, dapat menawarkan performa yang lebih cepat.

Kumpulan SQL tanpa server mendukung tabel sementara. Akan tetapi, penggunaannya terbatas karena Anda dapat memilih dari tabel sementara, tetapi tidak dapat menggabungkannya dengan file di penyimpanan.

Untuk informasi lebih lanjut, lihat Tabel sementara.

Tabel eksternal

Tabel eksternal mengarahkan ke data yang terletak di blob Azure Storage atau Azure Data Lake Storage.

Impor data dari tabel eksternal ke kumpulan SQL khusus menggunakan pernyataan CREATE TABLE AS SELECT. Untuk tutorial pemuatan, lihat Menggunakan PolyBase untuk memuat data dari Azure blob storage.

Untuk kumpulan SQL tanpa server, Anda bisa menggunakan CETAS untuk menyimpan hasil kueri ke tabel eksternal di Azure Storage.

Jenis data

Kumpulan SQL khusus mendukung jenis data yang paling umum digunakan. Untuk daftar jenis data yang didukung, lihat jenis data dalam referensi CREATE TABLE di pernyataan CREATE TABLE. Untuk informasi selengkapnya tentang penggunaan jenis data, lihat Jenis data.

Tabel terdistribusi

Fitur mendasar dari kumpulan SQL khusus adalah cara ia dapat menyimpan dan beroperasi pada tabel di seluruh distribusi. Kumpulan SQL khusus mendukung tiga metode untuk mendistribusikan data:

  • Round-robin (default)
  • Hash
  • Direplikasi

Tabel terdistribusi hash

Tabel terdistribusi hash mendistribusikan baris berdasarkan nilai di kolom distribusi. Tabel terdistribusi hash dirancang untuk mencapai performa tinggi untuk kueri pada tabel besar. Ada beberapa faktor yang perlu dipertimbangkan saat memilih kolom distribusi.

Untuk informasi lebih lanjut, lihat Panduan desain untuk tabel terdistribusi.

Tabel yang direplikasi

Tabel yang direplikasi memiliki salinan tabel lengkap yang tersedia di setiap simpul Komputasi. Kueri berjalan cepat pada tabel yang direplikasi karena bergabung pada tabel yang direplikasi tidak memerlukan perpindahan data. Replikasi membutuhkan penyimpanan ekstra dan tidak praktis untuk tabel besar.

Untuk informasi selengkapnya, lihat Panduan desain untuk tabel yang direplikasi.

Tabel round-robin

Tabel round-robin mendistribusikan baris tabel secara merata di semua distribusi. Baris didistribusikan secara acak. Memuat data ke dalam tabel round-robin sangatlah cepat. Akan tetapi, kueri dapat memerlukan lebih banyak pergerakan data daripada metode distribusi lainnya.

Untuk informasi selengkapnya, lihat Panduan desain untuk tabel terdistribusi.

Metode distribusi umum untuk tabel

Kategori tabel sering kali menentukan opsi optimal untuk distribusi tabel.

Kategori tabel Opsi distribusi yang disarankan
Fakta Gunakan distribusi hash dengan indeks penyimpan kolom berkluster. Performa meningkat ketika dua tabel hash digabungkan pada kolom distribusi yang sama.
Dimensi Gunakan direplikasi untuk tabel yang lebih kecil. Jika tabel terlalu besar untuk disimpan pada setiap simpul Komputasi, gunakan hash yang didistribusikan.
Staging Gunakan round-robin untuk tabel pentahapan. Beban dengan CTAS cepat. Setelah data berada dalam tabel staging, gunakan SISIPKAN...PILIH untuk memindahkan data ke tabel produksi.

Partisi

Dalam kumpulan SQL khusus, tabel berpartisi menyimpan dan menjalankan operasi pada baris tabel sesuai dengan rentang data. Misalnya, tabel dapat dipartisi berdasarkan hari, bulan, atau tahun. Anda dapat meningkatkan performa kueri melalui penghapusan partisi yang membatasi pemindaian kueri ke data dalam partisi.

Anda juga dapat mempertahankan data melalui pengalihan partisi. Karena data dalam kumpulan SQL khusus sudah didistribusikan, terlalu banyak partisi dapat memperlambat performa kueri. Untuk informasi selengkapnya, lihat Panduan pemartisian.

Tip

Saat partisi beralih ke partisi tabel yang tidak kosong, pertimbangkan untuk menggunakan opsi TRUNCATE_TARGET dalam pernyataan ALTER TABLE Anda jika data yang ada akan dipotong.

Kode di bawah ini mengalihkan data harian yang ditransformasi menjadi partisi SalesFact dan menimpa data yang sudah ada.

ALTER TABLE SalesFact_DailyFinalLoad SWITCH PARTITION 256 TO SalesFact PARTITION 256 WITH (TRUNCATE_TARGET = ON);  

Dalam kumpulan SQL tanpa server, Anda dapat membatasi file/folder (partisi) yang akan dibaca oleh kueri Anda. Pemartisian menurut jalur didukung menggunakan fungsi filepath dan fileinfo yang dijelaskan dalam Mengkueri file penyimpanan. Contoh berikut membaca folder dengan data untuk tahun 2017:

SELECT
    nyc.filepath(1) AS [year],
    payment_type,
    SUM(fare_amount) AS fare_total
FROM  
    OPENROWSET(
        BULK 'https://sqlondemandstorage.blob.core.windows.net/parquet/taxi/year=*/month=*/*.parquet',
        FORMAT='PARQUET'
    ) AS nyc
WHERE
    nyc.filepath(1) = 2017
GROUP BY
    nyc.filepath(1),
    payment_type
ORDER BY
    nyc.filepath(1),
    payment_type

Indeks penyimpan kolom

Secara default, kumpulan SQL khusus menyimpan tabel sebagai indeks penyimpan kolom berkluster. Bentuk penyimpanan data ini mencapai kompresi data dan performa kueri yang tinggi pada tabel besar. Indeks penyimpan kolom berkluster biasanya merupakan pilihan terbaik, tetapi dalam beberapa kasus indeks berkluster atau bertumpuk merupakan struktur penyimpanan yang sesuai.

Tip

Tabel heap dapat sangat berguna untuk memuat data sementara, seperti tabel staging, yang diubah menjadi tabel akhir.

Untuk daftar fitur penyimpanan kolom, lihat Apa yang baru untuk indeks penyimpan kolom. Untuk meningkatkan performa indeks penyimpan kolom, lihat Memaksimalkan kualitas grup baris untuk indeks penyimpan kolom.

Statistik

Pengoptimal kueri menggunakan statistik tingkat kolom saat membuat rencana untuk menjalankan kueri. Untuk meningkatkan performa kueri, penting untuk memiliki statistik pada kolom individual, terutama kolom yang digunakan dalam gabungan kueri. Synapse SQL mendukung pembuatan statistik secara otomatis.

Pembaruan statistik tidak terjadi secara otomatis. Lakukan pembaruan statistik setelah sejumlah besar baris ditambahkan atau diubah. Misalnya, lakukan pembaruan statistik setelah pemuatan. Informasi tambahan disediakan di artikel Panduan statistik.

Kunci primer dan kunci unik

Untuk kumpulan SQL khusus, KUNCI PRIMER hanya didukung ketika NONCLUSTERED dan NOT ENFORCED keduanya digunakan. Batasan UNIQUE hanya didukung ketika NOT ENFORCED digunakan. Untuk informasi selengkapnya, lihat artikel batasan tabel kolam SQL khusus.

Perintah untuk membuat tabel

Untuk kumpulan SQL khusus, Anda dapat membuat tabel sebagai tabel kosong baru. Anda juga dapat membuat dan mengisi tabel dengan hasil dari pernyataan pilih. Berikut perintah T-SQL untuk membuat tabel.

Pernyataan T-SQL Deskripsi
CREATE TABLE Membuat tabel kosong dengan menentukan semua kolom dan opsi tabel.
CREATE EXTERNAL TABLE Membuat tabel eksternal. Definisi tabel disimpan di kumpulan SQL khusus. Data tabel disimpan di Azure Blob storage atau Azure Data Lake Storage.
CREATE TABLE AS SELECT Mengisi tabel baru dengan hasil dari pernyataan pilih. Kolom tabel dan jenis data didasarkan pada hasil pernyataan pilih. Untuk mengimpor data, pernyataan ini dapat memilih dari tabel eksternal.
CREATE EXTERNAL TABLE AS SELECT Membuat tabel eksternal baru dengan mengekspor hasil pernyataan pilih ke lokasi eksternal. Lokasinya di Azure Blob storage atau Azure Data Lake Storage.

Selaraskan data sumber dengan gudang data

Tabel kumpulan SQL khusus diisi dengan memuat data dari sumber data lain. Untuk mencapai beban yang berhasil, jumlah dan jenis data kolom pada data sumber harus selaras dengan definisi tabel di gudang data.

Catatan

Menyelaraskan data mungkin merupakan bagian tersulit dalam mendesain tabel Anda.

Jika data berasal dari beberapa penyimpanan data, Anda dapat mentransfer data ke gudang data dan menyimpannya dalam tabel integrasi. Setelah data berada dalam tabel integrasi, Anda dapat menggunakan kekuatan kumpulan SQL khusus untuk menerapkan operasi transformasi. Setelah data disiapkan, Anda dapat menyisipkannya ke dalam tabel produksi.

Fitur tabel yang tidak didukung

Kumpulan SQL khusus mendukung banyak fitur tabel, tetapi tidak semua, yang ditawarkan oleh database lain. Daftar berikut ini memperlihatkan beberapa fitur tabel yang tidak didukung di kumpulan SQL khusus.

Kueri ukuran tabel

Dalam kumpulan SQL khusus, salah satu cara sederhana untuk mengidentifikasi ruang dan baris yang dipakai oleh tabel pada masing-masing dari 60 distribusi adalah dengan menggunakan DBCC PDW_SHOWSPACEUSED.

DBCC PDW_SHOWSPACEUSED('dbo.FactInternetSales');

Perlu diingat bahwa menggunakan perintah DBCC bisa sangat membatasi. Tampilan manajemen dinamis (DMV) menampilkan lebih banyak detail daripada perintah DBCC. Mulailah dengan membuat tampilan di bawah ini.

CREATE VIEW dbo.vTableSizes
AS
WITH base
AS
(
SELECT
 GETDATE()                                                             AS  [execution_time]
, DB_NAME()                                                            AS  [database_name]
, s.name                                                               AS  [schema_name]
, t.name                                                               AS  [table_name]
, QUOTENAME(s.name)+'.'+QUOTENAME(t.name)                              AS  [two_part_name]
, nt.[name]                                                            AS  [node_table_name]
, ROW_NUMBER() OVER(PARTITION BY nt.[name] ORDER BY (SELECT NULL))     AS  [node_table_name_seq]
, tp.[distribution_policy_desc]                                        AS  [distribution_policy_name]
, c.[name]                                                             AS  [distribution_column]
, nt.[distribution_id]                                                 AS  [distribution_id]
, i.[type]                                                             AS  [index_type]
, i.[type_desc]                                                        AS  [index_type_desc]
, nt.[pdw_node_id]                                                     AS  [pdw_node_id]
, pn.[type]                                                            AS  [pdw_node_type]
, pn.[name]                                                            AS  [pdw_node_name]
, di.name                                                              AS  [dist_name]
, di.position                                                          AS  [dist_position]
, nps.[partition_number]                                               AS  [partition_nmbr]
, nps.[reserved_page_count]                                            AS  [reserved_space_page_count]
, nps.[reserved_page_count] - nps.[used_page_count]                    AS  [unused_space_page_count]
, nps.[in_row_data_page_count]
    + nps.[row_overflow_used_page_count]
    + nps.[lob_used_page_count]                                        AS  [data_space_page_count]
, nps.[reserved_page_count]
 - (nps.[reserved_page_count] - nps.[used_page_count])
 - ([in_row_data_page_count]
         + [row_overflow_used_page_count]+[lob_used_page_count])       AS  [index_space_page_count]
, nps.[row_count]                                                      AS  [row_count]
from
    sys.schemas s
INNER JOIN sys.tables t
    ON s.[schema_id] = t.[schema_id]
INNER JOIN sys.indexes i
    ON  t.[object_id] = i.[object_id]
    AND i.[index_id] <= 1
INNER JOIN sys.pdw_table_distribution_properties tp
    ON t.[object_id] = tp.[object_id]
INNER JOIN sys.pdw_table_mappings tm
    ON t.[object_id] = tm.[object_id]
INNER JOIN sys.pdw_nodes_tables nt
    ON tm.[physical_name] = nt.[name]
INNER JOIN sys.dm_pdw_nodes pn
    ON  nt.[pdw_node_id] = pn.[pdw_node_id]
INNER JOIN sys.pdw_distributions di
    ON  nt.[distribution_id] = di.[distribution_id]
INNER JOIN sys.dm_pdw_nodes_db_partition_stats nps
    ON nt.[object_id] = nps.[object_id]
    AND nt.[pdw_node_id] = nps.[pdw_node_id]
    AND nt.[distribution_id] = nps.[distribution_id]
LEFT OUTER JOIN (select * from sys.pdw_column_distribution_properties where distribution_ordinal = 1) cdp
    ON t.[object_id] = cdp.[object_id]
LEFT OUTER JOIN sys.columns c
    ON cdp.[object_id] = c.[object_id]
    AND cdp.[column_id] = c.[column_id]
WHERE pn.[type] = 'COMPUTE'
)
, size
AS
(
SELECT
   [execution_time]
,  [database_name]
,  [schema_name]
,  [table_name]
,  [two_part_name]
,  [node_table_name]
,  [node_table_name_seq]
,  [distribution_policy_name]
,  [distribution_column]
,  [distribution_id]
,  [index_type]
,  [index_type_desc]
,  [pdw_node_id]
,  [pdw_node_type]
,  [pdw_node_name]
,  [dist_name]
,  [dist_position]
,  [partition_nmbr]
,  [reserved_space_page_count]
,  [unused_space_page_count]
,  [data_space_page_count]
,  [index_space_page_count]
,  [row_count]
,  ([reserved_space_page_count] * 8.0)                                 AS [reserved_space_KB]
,  ([reserved_space_page_count] * 8.0)/1000                            AS [reserved_space_MB]
,  ([reserved_space_page_count] * 8.0)/1000000                         AS [reserved_space_GB]
,  ([reserved_space_page_count] * 8.0)/1000000000                      AS [reserved_space_TB]
,  ([unused_space_page_count]   * 8.0)                                 AS [unused_space_KB]
,  ([unused_space_page_count]   * 8.0)/1000                            AS [unused_space_MB]
,  ([unused_space_page_count]   * 8.0)/1000000                         AS [unused_space_GB]
,  ([unused_space_page_count]   * 8.0)/1000000000                      AS [unused_space_TB]
,  ([data_space_page_count]     * 8.0)                                 AS [data_space_KB]
,  ([data_space_page_count]     * 8.0)/1000                            AS [data_space_MB]
,  ([data_space_page_count]     * 8.0)/1000000                         AS [data_space_GB]
,  ([data_space_page_count]     * 8.0)/1000000000                      AS [data_space_TB]
,  ([index_space_page_count]  * 8.0)                                   AS [index_space_KB]
,  ([index_space_page_count]  * 8.0)/1000                              AS [index_space_MB]
,  ([index_space_page_count]  * 8.0)/1000000                           AS [index_space_GB]
,  ([index_space_page_count]  * 8.0)/1000000000                        AS [index_space_TB]
FROM base
)
SELECT *
FROM size
;

Ringkasan ruang tabel

Kueri ini menampilkan baris dan spasi menurut tabel. Ringkasan ruang tabel memungkinkan Anda untuk melihat tabel mana yang merupakan tabel terbesar Anda. Anda juga akan melihat apakah mereka round-robin, direplikasi, atau terdistribusi hash. Untuk tabel terdistribusi hash, kueri memperlihatkan kolom distribusi.

SELECT
     database_name
,    schema_name
,    table_name
,    distribution_policy_name
,      distribution_column
,    index_type_desc
,    COUNT(distinct partition_nmbr) as nbr_partitions
,    SUM(row_count)                 as table_row_count
,    SUM(reserved_space_GB)         as table_reserved_space_GB
,    SUM(data_space_GB)             as table_data_space_GB
,    SUM(index_space_GB)            as table_index_space_GB
,    SUM(unused_space_GB)           as table_unused_space_GB
FROM
    dbo.vTableSizes
GROUP BY
     database_name
,    schema_name
,    table_name
,    distribution_policy_name
,      distribution_column
,    index_type_desc
ORDER BY
    table_reserved_space_GB desc
;

Ruang tabel menurut jenis distribusi

SELECT
     distribution_policy_name
,    SUM(row_count)                as table_type_row_count
,    SUM(reserved_space_GB)        as table_type_reserved_space_GB
,    SUM(data_space_GB)            as table_type_data_space_GB
,    SUM(index_space_GB)           as table_type_index_space_GB
,    SUM(unused_space_GB)          as table_type_unused_space_GB
FROM dbo.vTableSizes
GROUP BY distribution_policy_name
;

Ruang tabel menurut jenis indeks

SELECT
     index_type_desc
,    SUM(row_count)                as table_type_row_count
,    SUM(reserved_space_GB)        as table_type_reserved_space_GB
,    SUM(data_space_GB)            as table_type_data_space_GB
,    SUM(index_space_GB)           as table_type_index_space_GB
,    SUM(unused_space_GB)          as table_type_unused_space_GB
FROM dbo.vTableSizes
GROUP BY index_type_desc
;

Ringkasan ruang distribusi

SELECT
    distribution_id
,    SUM(row_count)                as total_node_distribution_row_count
,    SUM(reserved_space_MB)        as total_node_distribution_reserved_space_MB
,    SUM(data_space_MB)            as total_node_distribution_data_space_MB
,    SUM(index_space_MB)           as total_node_distribution_index_space_MB
,    SUM(unused_space_MB)          as total_node_distribution_unused_space_MB
FROM dbo.vTableSizes
GROUP BY     distribution_id
ORDER BY    distribution_id
;

Langkah berikutnya

Setelah membuat tabel untuk gudang data Anda, langkah berikutnya adalah memuat data ke dalam tabel. Untuk tutorial pemuatan, lihat Memuat data ke dalam kumpulan SQL khusus.