Dalam database Spanner, Spanner secara otomatis membuat
indeks untuk kunci utama setiap tabel. Misalnya, Anda tidak perlu melakukan apa pun untuk mengindeks kunci utama Singers
, karena kunci tersebut akan otomatis diindeks untuk Anda.
Anda juga dapat membuat indeks sekunder untuk kolom lain. Menambahkan indeks sekunder pada kolom akan membuat pencarian data di kolom tersebut lebih efisien. Misalnya, jika perlu mencari album berdasarkan judul dengan cepat, Anda harus
membuat indeks sekunder di AlbumTitle
,
sehingga Spanner tidak perlu memindai seluruh tabel.
Jika pencarian dalam contoh di atas dilakukan dalam transaksi baca-tulis, pencarian yang lebih efisien juga menghindari penahanan kunci di seluruh tabel, yang
memungkinkan penyisipan dan pembaruan serentak pada tabel untuk baris di luar
rentang pencarian AlbumTitle
.
Selain manfaat yang diberikan pada pencarian, indeks sekunder juga dapat membantu Spanner mengeksekusi pemindaian dengan lebih efisien, sehingga memungkinkan pemindaian indeks, bukan pemindaian tabel penuh.
Spanner menyimpan data berikut di setiap indeks sekunder:
- Semua kolom kunci dari tabel dasar
- Semua kolom yang dimasukkan dalam indeks
- Semua kolom yang ditentukan dalam klausa
STORING
opsional (database dialek GoogleSQL) atau klausaINCLUDE
(database dialek PostgreSQL) dari definisi indeks.
Seiring waktu, Spanner akan menganalisis tabel Anda untuk memastikan bahwa indeks sekunder digunakan untuk kueri yang sesuai.
Menambahkan indeks sekunder
Waktu paling efisien untuk menambahkan indeks sekunder adalah saat Anda membuat tabel. Untuk membuat tabel dan indeksnya secara bersamaan, kirim pernyataan DDL untuk tabel baru dan indeks baru dalam satu permintaan ke Spanner.
Di Spanner, Anda juga dapat menambahkan indeks sekunder baru ke tabel yang sudah ada sementara database terus menyalurkan traffic. Seperti perubahan skema lainnya di Spanner, menambahkan indeks ke database yang ada tidak mengharuskan database tersebut offline dan tidak mengunci seluruh kolom atau tabel.
Setiap kali indeks baru ditambahkan ke tabel yang ada, Spanner akan otomatis melakukan pengisian ulang, atau mengisi, indeks untuk mencerminkan tampilan terbaru dari data yang sedang diindeks. Spanner mengelola proses pengisian ulang ini untuk Anda, dan proses tersebut berjalan di latar belakang menggunakan resource node dengan prioritas rendah. Pada umumnya, Anda tidak dapat mempercepat prosesnya (misalnya dengan menambahkan lebih banyak node), dan pengisian ulang tidak memengaruhi performa database secara signifikan.
Pembuatan indeks dapat memerlukan waktu beberapa menit hingga beberapa jam. Karena pembuatan indeks adalah update skema, indeks tersebut terikat oleh batasan performa yang sama dengan update skema lainnya. Waktu yang diperlukan untuk membuat indeks sekunder bergantung pada beberapa faktor:
- Ukuran {i>dataset<i}
- Kapasitas komputasi instance
- Beban pada instance
Untuk melihat progres yang dibuat untuk proses pengisian ulang indeks, lihat bagian progres.
Perhatikan bahwa menggunakan kolom stempel waktu commit sebagai bagian pertama dari indeks sekunder dapat membuat hotspot dan mengurangi performa penulisan.
Gunakan pernyataan CREATE INDEX
untuk menentukan indeks sekunder
dalam skema Anda. Berikut beberapa contohnya:
Untuk mengindeks semua Singers
dalam database menurut nama depan dan belakangnya:
GoogleSQL
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName);
PostgreSQL
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName);
Untuk membuat indeks semua Songs
dalam database dengan nilai SongName
:
GoogleSQL
CREATE INDEX SongsBySongName ON Songs(SongName);
PostgreSQL
CREATE INDEX SongsBySongName ON Songs(SongName);
Untuk mengindeks lagu saja dari penyanyi tertentu, gunakan
klausa INTERLEAVE IN
untuk menyisipkan indeks dalam
tabel Singers
:
GoogleSQL
CREATE INDEX SongsBySingerSongName ON Songs(SingerId, SongName),
INTERLEAVE IN Singers;
PostgreSQL
CREATE INDEX SongsBySingerSongName ON Songs(SingerId, SongName)
INTERLEAVE IN Singers;
Untuk mengindeks lagu di album tertentu saja:
GoogleSQL
CREATE INDEX SongsBySingerAlbumSongName ON Songs(SingerId, AlbumId, SongName),
INTERLEAVE IN Albums;
PostgreSQL
CREATE INDEX SongsBySingerAlbumSongName ON Songs(SingerId, AlbumId, SongName)
INTERLEAVE IN Albums;
Untuk mengindeks dengan urutan menurun dari SongName
:
GoogleSQL
CREATE INDEX SongsBySingerAlbumSongNameDesc ON Songs(SingerId, AlbumId, SongName DESC),
INTERLEAVE IN Albums;
PostgreSQL
CREATE INDEX SongsBySingerAlbumSongNameDesc ON Songs(SingerId, AlbumId, SongName DESC)
INTERLEAVE IN Albums;
Perlu diperhatikan bahwa anotasi DESC
di atas hanya berlaku untuk SongName
. Untuk mengindeks dengan urutan menurun kunci indeks lainnya, anotasikan juga dengan DESC
: SingerId DESC, AlbumId DESC
.
Perhatikan juga bahwa PRIMARY_KEY
adalah kata yang dicadangkan dan tidak dapat digunakan sebagai nama
indeks. Ini adalah nama yang diberikan pada indeks pseudo
yang dibuat ketika tabel dengan spesifikasi PRIMARY KEY dibuat
Untuk mengetahui detail selengkapnya dan praktik terbaik dalam memilih indeks non-disisipkan dan indeks sisipan, lihat Opsi indeks dan Menggunakan indeks sisipan pada kolom yang nilainya meningkat atau menurun secara monoton.
Memeriksa progres pengisian ulang indeks
Konsol
Di menu navigasi Spanner, klik tab Operations. Halaman Operations menampilkan daftar operasi yang sedang berjalan.
Temukan operasi pengisian ulang dalam daftar. Jika masih berjalan, indikator progres di kolom Waktu berakhir akan menampilkan persentase operasi yang selesai, seperti yang ditunjukkan pada gambar berikut:
gcloud
Gunakan gcloud spanner operations describe
untuk memeriksa progres operasi.
Dapatkan ID operasi:
gcloud spanner operations list --instance=INSTANCE-NAME \ --database=DATABASE-NAME --type=DATABASE_UPDATE_DDL
Ganti kode berikut:
- INSTANCE-NAME dengan nama instance Spanner.
- DATABASE-NAME dengan nama database.
Catatan penggunaan:
Untuk membatasi daftar, tentukan flag
--filter
. Contoh:--filter="metadata.name:example-db"
hanya mencantumkan operasi pada database tertentu.--filter="error:*"
hanya mencantumkan operasi pencadangan yang gagal.
Untuk mengetahui informasi tentang sintaksis filter, lihat gcloud topic filters. Untuk mengetahui informasi tentang cara memfilter operasi pencadangan, lihat kolom
filter
di ListBackupOperationsRequest.Flag
--type
tidak peka huruf besar/kecil.
Outputnya terlihat mirip dengan yang berikut ini:
OPERATION_ID STATEMENTS DONE @TYPE _auto_op_123456 CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName) False UpdateDatabaseDdlMetadata CREATE INDEX SongsBySingerAlbumSongName ON Songs(SingerId, AlbumId, SongName), INTERLEAVE IN Albums _auto_op_234567 True CreateDatabaseMetadata
Jalankan
gcloud spanner operations describe
:gcloud spanner operations describe \ --instance=INSTANCE-NAME \ --database=DATABASE-NAME \ projects/PROJECT-NAME/instances/INSTANCE-NAME/databases/DATABASE-NAME/operations/OPERATION_ID
Ganti kode berikut:
- INSTANCE-NAME: Nama instance Spanner.
- DATABASE-NAME: Nama database Spanner.
- PROJECT-NAME: Nama project.
- OPERATION-ID: ID operasi dari operasi yang ingin Anda periksa.
Bagian
progress
pada output menunjukkan persentase operasi yang selesai. Outputnya terlihat mirip dengan berikut ini:done: true ... progress: - endTime: '2021-01-22T21:58:42.912540Z' progressPercent: 100 startTime: '2021-01-22T21:58:11.053996Z' - progressPercent: 67 startTime: '2021-01-22T21:58:11.053996Z' ...
REST v1
Dapatkan ID operasi:
gcloud spanner operations list --instance=INSTANCE-NAME
--database=DATABASE-NAME --type=DATABASE_UPDATE_DDL
Ganti kode berikut:
- INSTANCE-NAME dengan nama instance Spanner.
- DATABASE-NAME dengan nama database.
Sebelum menggunakan salah satu data permintaan, lakukan penggantian berikut:
- project-id: Project ID.
- instance-id: ID instance.
- database-id: ID database.
- operation-id: ID operasi.
Metode HTTP dan URL:
GET https://spanner.googleapis.com/v1/projects/project-id/instances/instance-id/databases/database-id/operations/operation-id
Untuk mengirim permintaan, perluas salah satu opsi berikut:
Anda akan melihat respons JSON seperti berikut:
{ ... "progress": [ { "progressPercent": 100, "startTime": "2023-05-27T00:52:27.366688Z", "endTime": "2023-05-27T00:52:30.184845Z" }, { "progressPercent": 100, "startTime": "2023-05-27T00:52:30.184845Z", "endTime": "2023-05-27T00:52:40.750959Z" } ], ... "done": true, "response": { "@type": "type.googleapis.com/google.protobuf.Empty" } }
Untuk gcloud
dan REST, Anda dapat menemukan progres setiap pernyataan pengisian ulang indeks di bagian progress
. Untuk setiap pernyataan dalam array pernyataan,
ada kolom yang sesuai dalam array progres. Urutan array progres ini sesuai dengan urutan array pernyataan. Setelah tersedia, kolom
startTime
, progressPercent
, dan endTime
akan diisi dengan sesuai.
Perhatikan bahwa output tidak menunjukkan perkiraan waktu kapan progres
pengisian ulang akan selesai.
Jika operasi berlangsung terlalu lama, Anda dapat membatalkannya. Untuk mengetahui informasi selengkapnya, lihat Membatalkan pembuatan indeks.
Skenario saat melihat progres pengisian ulang indeks
Ada berbagai skenario yang dapat Anda temui saat mencoba memeriksa progres pengisian ulang indeks. Pernyataan pembuatan indeks yang memerlukan pengisian ulang indeks adalah bagian dari operasi update skema, dan mungkin ada beberapa pernyataan yang merupakan bagian dari operasi update skema.
Skenario pertama adalah yang paling sederhana, yaitu ketika pernyataan pembuatan indeks adalah pernyataan pertama dalam operasi pembaruan skema. Karena pernyataan pembuatan indeks adalah pernyataan pertama, pernyataan tersebut adalah yang pertama diproses dan dieksekusi karena urutan eksekusi.
Segera, kolom startTime
dari pernyataan pembuatan indeks akan segera diisi dengan waktu mulai operasi pembaruan skema. Selanjutnya, kolom progressPercent
pernyataan pembuatan indeks diisi saat progres pengisian ulang indeks di atas 0%. Terakhir, kolom endTime
akan terisi setelah pernyataan di-commit.
Skenario kedua adalah saat pernyataan pembuatan indeks bukan pernyataan pertama dalam operasi pembaruan skema. Tidak ada kolom yang terkait dengan pernyataan pembuatan indeks yang akan diisi hingga pernyataan sebelumnya di-commit karena urutan eksekusi.
Serupa dengan skenario di atas, setelah pernyataan sebelumnya di-commit, kolom startTime
dalam pernyataan pembuatan indeks akan diisi terlebih dahulu, diikuti dengan kolom progressPercent
. Terakhir, kolom endTime
akan diisi setelah pernyataan selesai di-commit.
Batalkan pembuatan indeks
Anda dapat menggunakan Google Cloud CLI untuk membatalkan pembuatan indeks. Untuk mengambil daftar operasi pembaruan skema untuk database Spanner, gunakan perintah gcloud spanner operations list
, dan sertakan opsi --filter
:
gcloud spanner operations list \
--instance=INSTANCE \
--database=DATABASE \
--filter="@TYPE:UpdateDatabaseDdlMetadata"
Temukan OPERATION_ID
untuk operasi yang ingin Anda batalkan, lalu gunakan
perintah gcloud spanner operations cancel
untuk
membatalkannya:
gcloud spanner operations cancel OPERATION_ID \
--instance=INSTANCE \
--database=DATABASE
Lihat indeks yang ada
Untuk melihat informasi tentang indeks yang ada dalam database, Anda dapat menggunakan Konsol Google Cloud atau Google Cloud CLI:
Konsol
Buka halaman Instance Spanner di Konsol Google Cloud.
Klik nama instance yang ingin Anda lihat.
Di panel kiri, klik database yang ingin Anda lihat, lalu klik tabel yang ingin Anda lihat.
Klik tab Indeks. Konsol Google Cloud akan menampilkan daftar indeks.
Opsional: Untuk mendapatkan detail tentang indeks, seperti kolom yang tercakup, klik nama indeks.
gcloud
Gunakan perintah gcloud spanner databases ddl describe
:
gcloud spanner databases ddl describe DATABASE \
--instance=INSTANCE
Gcloud CLI mencetak pernyataan Data Definition Language (DDL) untuk membuat tabel dan indeks database. Pernyataan CREATE
INDEX
menjelaskan indeks yang ada. Misalnya:
--- |-
CREATE TABLE Singers (
SingerId INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
SingerInfo BYTES(MAX),
) PRIMARY KEY(SingerId)
---
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName)
Kueri dengan indeks tertentu
Bagian berikut menjelaskan cara menentukan indeks dalam pernyataan SQL dan
dengan antarmuka baca untuk Spanner. Contoh di bagian ini
mengasumsikan bahwa Anda menambahkan kolom MarketingBudget
ke tabel Albums
dan
membuat indeks yang disebut AlbumsByAlbumTitle
:
GoogleSQL
CREATE TABLE Albums (
SingerId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
MarketingBudget INT64,
) PRIMARY KEY (SingerId, AlbumId),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE;
CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle);
PostgreSQL
CREATE TABLE Albums (
SingerId BIGINT NOT NULL,
AlbumId BIGINT NOT NULL,
AlbumTitle VARCHAR,
MarketingBudget BIGINT,
PRIMARY KEY (SingerId, AlbumId)
) INTERLEAVE IN PARENT Singers ON DELETE CASCADE;
CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle);
Menentukan indeks dalam pernyataan SQL
Saat Anda menggunakan SQL untuk membuat kueri tabel Spanner, Spanner secara otomatis akan menggunakan indeks apa pun yang cenderung membuat kueri lebih efisien. Dengan demikian, Anda tidak perlu menentukan indeks untuk kueri SQL. Namun,
untuk kueri yang sangat penting bagi beban kerja Anda, Google menyarankan agar menggunakan
perintah FORCE_INDEX
dalam pernyataan SQL Anda untuk performa yang lebih konsisten.
Dalam beberapa kasus, Spanner dapat memilih indeks yang menyebabkan peningkatan latensi kueri. Jika telah mengikuti langkah-langkah pemecahan masalah untuk regresi performa dan mengonfirmasi bahwa sebaiknya mencoba indeks yang berbeda untuk kueri, Anda dapat menentukan indeks sebagai bagian dari kueri.
Untuk menentukan indeks dalam pernyataan SQL, gunakan petunjuk FORCE_INDEX
untuk memberikan perintah indeks. Perintah indeks menggunakan sintaksis berikut:
GoogleSQL
FROM MyTable@{FORCE_INDEX=MyTableIndex}
PostgreSQL
FROM MyTable /*@ FORCE_INDEX = MyTableIndex */
Anda juga dapat menggunakan perintah indeks untuk memberi tahu Spanner agar memindai tabel dasar, bukan menggunakan indeks:
GoogleSQL
FROM MyTable@{FORCE_INDEX=_BASE_TABLE}
PostgreSQL
FROM MyTable /*@ FORCE_INDEX = _BASE_TABLE */
Contoh berikut menunjukkan kueri SQL yang menentukan indeks:
GoogleSQL
SELECT AlbumId, AlbumTitle, MarketingBudget
FROM Albums@{FORCE_INDEX=AlbumsByAlbumTitle}
WHERE AlbumTitle >= "Aardvark" AND AlbumTitle < "Goo";
PostgreSQL
SELECT AlbumId, AlbumTitle, MarketingBudget
FROM Albums /*@ FORCE_INDEX = AlbumsByAlbumTitle */
WHERE AlbumTitle >= 'Aardvark' AND AlbumTitle < 'Goo';
Perintah indeks dapat memaksa pemroses kueri Spanner untuk membaca kolom tambahan yang diperlukan oleh kueri, tetapi tidak disimpan dalam indeks.
Pemroses kueri mengambil kolom tersebut dengan menggabungkan indeks dan tabel dasar. Untuk menghindari gabungan tambahan ini, gunakan klausa STORING
(database dialek GoogleSQL) atau klausa INCLUDE
(database dialek PostgreSQL) untuk menyimpan kolom tambahan dalam indeks.
Misalnya, pada contoh yang ditampilkan di atas, kolom MarketingBudget
tidak
disimpan dalam indeks, tetapi kueri SQL memilih kolom ini. Akibatnya,
Spanner harus mencari kolom MarketingBudget
dalam tabel dasar,
lalu menggabungkannya dengan data dari indeks, untuk menampilkan hasil kueri.
Spanner akan menimbulkan error jika perintah indeks memiliki salah satu masalah berikut:
- Indeks tidak ada.
- Indeks berada di tabel dasar yang berbeda.
- Kueri tidak memiliki ekspresi pemfilteran
NULL
yang diperlukan untuk indeksNULL_FILTERED
.
Contoh berikut menunjukkan cara menulis dan menjalankan kueri yang mengambil nilai AlbumId
, AlbumTitle
, dan MarketingBudget
menggunakan indeks AlbumsByAlbumTitle
:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Menentukan indeks di antarmuka baca
Saat menggunakan antarmuka baca untuk Spanner, dan ingin Spanner menggunakan indeks, Anda harus menentukan indeksnya. Antarmuka baca tidak memilih indeks secara otomatis.
Selain itu, indeks Anda harus berisi semua data yang muncul dalam hasil kueri, tidak termasuk kolom yang merupakan bagian dari kunci utama. Batasan ini ada karena antarmuka baca tidak mendukung gabungan antara indeks dan tabel dasar. Jika Anda perlu menyertakan kolom lain dalam hasil kueri, Anda memiliki beberapa pilihan:
- Gunakan klausa
STORING
atauINCLUDE
untuk menyimpan kolom tambahan dalam indeks. - Buat kueri tanpa menyertakan kolom tambahan, lalu gunakan kunci utama untuk mengirim kueri lain yang membaca kolom tambahan.
Spanner menampilkan nilai dari indeks dalam tata urutan menaik berdasarkan kunci indeks. Untuk mengambil nilai dalam urutan menurun, selesaikan langkah-langkah berikut:
Anotasikan kunci indeks dengan
DESC
. Contoh:CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle DESC);
Anotasi
DESC
berlaku untuk satu kunci indeks. Jika indeks menyertakan lebih dari satu kunci, dan Anda ingin hasil kueri muncul dalam urutan menurun berdasarkan semua kunci, sertakan anotasiDESC
untuk setiap kunci.Jika pembacaan menentukan rentang kunci, pastikan rentang kunci tersebut juga dalam urutan menurun. Dengan kata lain, nilai kunci awal harus lebih besar dari nilai kunci akhir.
Contoh berikut menunjukkan cara mengambil nilai AlbumId
dan AlbumTitle
menggunakan indeks AlbumsByAlbumTitle
:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Buat indeks untuk pemindaian khusus indeks
Anda juga dapat menggunakan klausa STORING
(untuk database dialek GoogleSQL) atau klausa INCLUDE
(untuk database dialek PostgreSQL) untuk menyimpan salinan kolom dalam indeks. Jenis indeks ini memberikan keuntungan untuk kueri dan panggilan baca menggunakan indeks, dengan mengorbankan penyimpanan tambahan:
- Kueri SQL yang menggunakan indeks dan kolom tertentu yang disimpan dalam klausa
STORING
atauINCLUDE
tidak memerlukan gabungan tambahan ke tabel dasar. - Panggilan
read()
yang menggunakan indeks dapat membaca kolom yang disimpan oleh klausaSTORING
/INCLUDE
.
Misalnya, Anda membuat versi alternatif AlbumsByAlbumTitle
yang menyimpan salinan kolom MarketingBudget
di indeks (perhatikan klausa
STORING
atau INCLUDE
dalam cetak tebal):
GoogleSQL
CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget);
PostgreSQL
CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) INCLUDE (MarketingBudget);
Dengan indeks AlbumsByAlbumTitle
lama, Spanner harus menggabungkan indeks dengan tabel dasar, lalu mengambil kolom dari tabel dasar. Dengan indeks AlbumsByAlbumTitle2
yang baru, Spanner membaca kolom langsung dari indeks, sehingga lebih efisien.
Jika Anda menggunakan antarmuka baca, bukan SQL, indeks AlbumsByAlbumTitle2
yang baru juga memungkinkan Anda membaca kolom MarketingBudget
secara langsung:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Mengubah indeks
Anda dapat menggunakan pernyataan ALTER INDEX
untuk menambahkan kolom tambahan ke dalam indeks yang ada atau kolom lepas. Tindakan ini dapat memperbarui daftar kolom yang ditentukan oleh klausa STORING
(database dialek GoogleSQL) atau klausa INCLUDE
(database dialek PostgreSQL) saat Anda membuat indeks. Anda tidak dapat menggunakan pernyataan ini untuk menambahkan kolom ke atau menghapus kolom dari kunci indeks. Misalnya, daripada membuat indeks
baru AlbumsByAlbumTitle2
, Anda dapat menggunakan ALTER INDEX
untuk menambahkan
kolom ke AlbumsByAlbumTitle
, seperti yang ditunjukkan dalam contoh berikut:
GoogleSQL
ALTER INDEX AlbumsByAlbumTitle ADD STORED COLUMN MarketingBudget
PostgreSQL
ALTER INDEX AlbumsByAlbumTitle ADD INCLUDE COLUMN MarketingBudget
Saat Anda menambahkan kolom baru ke dalam indeks yang ada, Spanner
akan menggunakan proses pengisian ulang latar belakang. Saat pengisian ulang sedang berlangsung, kolom dalam indeks tidak dapat dibaca, sehingga Anda mungkin tidak mendapatkan peningkatan performa yang diharapkan. Anda dapat menggunakan perintah gcloud spanner operations
untuk menampilkan daftar operasi yang berjalan lama dan melihat statusnya.
Untuk informasi selengkapnya, lihat menjelaskan operasi.
Anda juga dapat menggunakan membatalkan operasi untuk membatalkan operasi yang sedang berjalan.
Setelah pengisian ulang selesai, Spanner akan menambahkan kolom ke indeks. Seiring dengan membesarnya Indeks, hal ini mungkin memperlambat kueri yang menggunakan indeks tersebut.
Contoh berikut menunjukkan cara menghapus kolom dari indeks:
GoogleSQL
ALTER INDEX AlbumsByAlbumTitle DROP STORED COLUMN MarketingBudget
PostgreSQL
ALTER INDEX AlbumsByAlbumTitle DROP INCLUDE COLUMN MarketingBudget
Indeks nilai NULL
Secara default, Spanner mengindeks NULL
nilai. Misalnya, ingat kembali definisi indeks SingersByFirstLastName
pada tabel Singers
:
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName);
Semua baris Singers
diindeks meskipun FirstName
atau LastName
, atau keduanya, adalah NULL
.
Saat nilai NULL
diindeks, Anda dapat menjalankan kueri SQL yang efisien dan membaca data yang menyertakan nilai NULL
. Misalnya, gunakan pernyataan kueri SQL ini
untuk menemukan semua Singers
dengan NULL
FirstName
:
GoogleSQL
SELECT s.SingerId, s.FirstName, s.LastName
FROM Singers@{FORCE_INDEX=SingersByFirstLastName} AS s
WHERE s.FirstName IS NULL;
PostgreSQL
SELECT s.SingerId, s.FirstName, s.LastName
FROM Singers /* @ FORCE_INDEX = SingersByFirstLastName */ AS s
WHERE s.FirstName IS NULL;
Urutan penyortiran untuk nilai NULL
Spanner mengurutkan NULL
sebagai nilai terkecil untuk jenis tertentu. Untuk
kolom dalam urutan menaik (ASC
), nilai NULL
akan diurutkan terlebih dahulu. Untuk kolom dalam urutan menurun (DESC
), nilai NULL
akan diurutkan terakhir.
Menonaktifkan pengindeksan nilai NULL
GoogleSQL
Untuk menonaktifkan pengindeksan null, tambahkan kata kunci NULL_FILTERED
ke definisi indeks. Indeks NULL_FILTERED
sangat berguna untuk mengindeks kolom sparse, yang sebagian besar barisnya berisi nilai NULL
. Dalam kasus ini, indeks NULL_FILTERED
dapat jauh lebih kecil dan lebih efisien untuk dikelola
daripada indeks normal yang menyertakan nilai NULL
.
Berikut adalah definisi alternatif dari SingersByFirstLastName
yang
tidak mengindeks nilai NULL
:
CREATE NULL_FILTERED INDEX SingersByFirstLastNameNoNulls
ON Singers(FirstName, LastName);
Kata kunci NULL_FILTERED
berlaku untuk semua kolom kunci indeks. Anda tidak dapat menentukan
pemfilteran NULL
per kolom.
PostgreSQL
Untuk memfilter baris dengan nilai null di satu atau beberapa kolom terindeks, gunakan
predikat WHERE COLUMN IS NOT NULL
.
Indeks yang difilter null sangat berguna untuk mengindeks kolom sparse, yang mana sebagian besar baris berisi nilai NULL
. Dalam kasus ini, indeks yang difilter dengan null dapat jauh lebih kecil dan lebih efisien untuk dikelola
daripada indeks normal yang menyertakan nilai NULL
.
Berikut adalah definisi alternatif dari SingersByFirstLastName
yang
tidak mengindeks nilai NULL
:
CREATE INDEX SingersByFirstLastNameNoNulls
ON Singers(FirstName, LastName)
WHERE FirstName IS NOT NULL
AND LastName IS NOT NULL;
Memfilter nilai NULL
akan mencegah Spanner menggunakannya untuk beberapa kueri. Misalnya, Spanner tidak menggunakan indeks untuk kueri ini,
karena indeks menghilangkan semua baris Singers
yang LastName
-nya adalah NULL
; akibatnya, penggunaan indeks akan mencegah kueri menampilkan baris yang benar:
GoogleSQL
FROM Singers@{FORCE_INDEX=SingersByFirstLastNameNoNulls}
WHERE FirstName = "John";
PostgreSQL
FROM Singers /*@ FORCE_INDEX = SingersByFirstLastNameNoNulls */
WHERE FirstName = 'John';
Agar Spanner dapat menggunakan indeks, Anda harus menulis ulang kueri agar Spanner tidak menyertakan baris yang juga dikecualikan dari indeks:
GoogleSQL
SELECT FirstName, LastName
FROM Singers@{FORCE_INDEX=SingersByFirstLastNameNoNulls}
WHERE FirstName = 'John' AND LastName IS NOT NULL;
PostgreSQL
SELECT FirstName, LastName
FROM Singers /*@ FORCE_INDEX = SingersByFirstLastNameNoNulls */
WHERE FirstName = 'John' AND LastName IS NOT NULL;
Indeks unik
Indeks dapat dideklarasikan sebagai UNIQUE
. Indeks UNIQUE
menambahkan batasan pada data yang diindeks, yang melarang entri duplikat untuk kunci indeks tertentu.
Batasan ini diterapkan oleh Spanner pada waktu commit transaksi.
Secara khusus, transaksi apa pun yang akan menyebabkan beberapa entri indeks untuk kunci yang sama ada akan gagal di-commit.
Jika tabel berisi data non-UNIQUE
di dalamnya pada awalnya, upaya untuk
membuat indeks UNIQUE
pada tabel tersebut akan gagal.
Catatan tentang indeks UNIQUE NULL_FILTERED
Indeks UNIQUE NULL_FILTERED
tidak menerapkan keunikan kunci indeks jika setidaknya salah satu bagian kunci indeks adalah NULL.
Sebagai contoh, anggaplah Anda membuat tabel dan indeks berikut:
GoogleSQL
CREATE TABLE ExampleTable (
Key1 INT64 NOT NULL,
Key2 INT64,
Key3 INT64,
Col1 INT64,
) PRIMARY KEY (Key1, Key2, Key3);
CREATE UNIQUE NULL_FILTERED INDEX ExampleIndex ON ExampleTable (Key1, Key2, Col1);
PostgreSQL
CREATE TABLE ExampleTable (
Key1 BIGINT NOT NULL,
Key2 BIGINT,
Key3 BIGINT,
Col1 BIGINT,
PRIMARY KEY (Key1, Key2, Key3)
);
CREATE UNIQUE INDEX ExampleIndex ON ExampleTable (Key1, Key2, Col1)
WHERE Key1 IS NOT NULL
AND Key2 IS NOT NULL
AND Col1 IS NOT NULL;
Dua baris di ExampleTable
berikut memiliki nilai yang sama untuk kunci indeks sekunder Key1
, Key2
, dan Col1
:
1, NULL, 1, 1
1, NULL, 2, 1
Karena Key2
adalah NULL
dan indeks difilter oleh null, baris tidak akan
ada dalam indeks ExampleIndex
. Karena nilai tersebut tidak disisipkan ke dalam indeks, indeks tidak akan menolaknya karena melanggar keunikan pada (Key1, Key2,
Col1)
.
Jika Anda ingin indeks menerapkan keunikan nilai tuple (Key1
,
Key2
, Col1
), Anda harus menganotasi Key2
dengan NOT NULL
dalam definisi tabel
atau membuat indeks tanpa memfilter null.
Meletakkan indeks
Gunakan pernyataan DROP INDEX
untuk menghapus indeks sekunder dari
skema Anda.
Untuk menghapus indeks bernama SingersByFirstLastName
:
DROP INDEX SingersByFirstLastName;
Indeks untuk pemindaian yang lebih cepat
Saat Spanner perlu melakukan pemindaian tabel (bukan pencarian yang diindeks) untuk mengambil nilai dari satu atau beberapa kolom, Anda dapat menerima hasil yang lebih cepat jika ada indeks untuk kolom tersebut, dan dalam urutan yang ditentukan oleh kueri. Jika Anda sering melakukan kueri yang memerlukan pemindaian, pertimbangkan untuk membuat indeks sekunder untuk membantu pemindaian ini terjadi dengan lebih efisien.
Secara khusus, jika Anda memerlukan Spanner untuk sering memindai kunci utama tabel atau indeks lainnya dalam urutan terbalik, Anda dapat meningkatkan efisiensinya melalui indeks sekunder yang membuat urutan yang diinginkan menjadi eksplisit.
Misalnya, kueri di bawah ini selalu menampilkan hasil yang cepat, meskipun
Spanner perlu memindai Songs
untuk menemukan nilai terendah
SongId
:
SELECT SongId FROM Songs LIMIT 1;
SongId
adalah kunci utama tabel, yang disimpan (seperti semua kunci utama)
dalam urutan menaik. Spanner dapat memindai indeks kunci tersebut
dan menemukan hasil pertama dengan cepat.
Namun, tanpa bantuan indeks sekunder, kueri berikut tidak akan
ditampilkan dengan cepat, terutama jika Songs
menyimpan banyak data:
SELECT SongId FROM Songs ORDER BY SongId DESC LIMIT 1;
Meskipun SongId
adalah kunci utama tabel, Spanner tidak memiliki cara untuk mengambil nilai tertinggi kolom tanpa menggunakan pemindaian tabel penuh.
Menambahkan indeks berikut akan memungkinkan kueri ini menampilkan lebih cepat:
CREATE INDEX SongIdDesc On Songs(SongId DESC);
Dengan menerapkan indeks ini, Spanner akan menggunakannya untuk menampilkan hasil kueri kedua dengan jauh lebih cepat.
Langkah selanjutnya
- Pelajari praktik terbaik SQL untuk Spanner.
- Memahami rencana eksekusi kueri untuk Spanner.
- Cari tahu cara memecahkan masalah regresi performa dalam kueri SQL.