Desain Basis Data: Tabel Baru versus Kolom Baru

38

(Ini disarankan untuk dikirim ulang di sini dari StackOverflow)

Saat ini memiliki tabel .. dan perlu mulai menambahkan kolom data baru ke dalamnya. Tidak setiap catatan (bahkan maju dengan data baru setelah menambahkan kolom data baru) akan memiliki data. Jadi saya bertanya-tanya apakah ini lebih cocok untuk tabel baru karena ini benar-benar merupakan perpanjangan dari beberapa baris data dan tidak berlaku untuk setiap baris.

Dengan kata lain, karena akan ada banyak kolom yang tidak digunakan untuk elemen-elemen data baru, sepertinya ini akan lebih cocok untuk tabel baru?

Tabel pertama adalah rekaman tampilan halaman (saat ini 2 juta catatan)

- id
- Alamat IP
- kali dilihat
- timestamp dibuat_at
- tanggal

untuk setiap alamat IP, catatan dibuat per hari - dan tampilan halaman berturut-turut ditambahkan ke tampilan kali per hari

bidang tambahan adalah untuk pelacakan titik asal (yaitu sumber / media / kampanye google analytics)

Tidak setiap kunjungan akan memiliki info itu. Saya akan berasumsi sekitar 10% dari baris akan memiliki data (karena biasanya hanya dikaitkan pada kunjungan pertama)

Penggunaan utama data adalah untuk atribut dari mana orang berasal. Ini mungkin berakhir lebih sering digunakan (yang kemudian tampaknya meminjamkan diri ke meja tunggal)

Menghargai umpan balik - dapat menambahkan lebih banyak jika diperlukan

cgmckeever
sumber

Jawaban:

29

Apa yang Anda geluti adalah pembagian vertikal. Ini adalah teknik desain basis data fisik untuk meningkatkan kinerja. Seperti halnya teknik desain database fisik, penerapannya tergantung pada permintaan spesifik yang Anda coba optimalkan dan apakah teknik ini akan mengoptimalkannya. Dari sudut pandang logis, jika bidang-bidang baru ini bergantung pada kunci kandidat untuk entitas Anda, maka itu adalah fakta tentang miliknya. Pertama, Anda harus memastikan bahwa Anda sepenuhnya memahami ketergantungan fungsional bidang baru ini pada kunci kandidat Anda untuk memverifikasi bahwa itu benar-benar fakta tentang tampilan halaman harian. Jika ya, memutuskan untuk mempartisi mereka ke dalam tabel lain adalah pengoptimalan kinerja yang seharusnya hanya dilakukan jika mencapai sasaran kinerja Anda.

Secara umum, partisi vertikal berguna jika Anda akan kueri kolom-kolom baru ini jarang dan berbeda dari kolom lain di tabel asli. Dengan menempatkan kolom-kolom itu di tabel lain yang membagikan PK yang sama dengan tabel yang ada, Anda dapat menanyakannya secara langsung ketika Anda menginginkan kolom-kolom baru tersebut dan mendapatkan hasil yang jauh lebih besar karena Anda akan memiliki lebih banyak baris per halaman pada disk untuk tabel baru ini. karena semua kolom dari tabel asli tidak akan duduk di baris itu. Namun, jika Anda akan selalu menanyakan kolom ini bersama dengan kolom di tabel asli maka partisi vertikal tidak akan masuk akal karena Anda harus selalu bergabung dengan luar untuk mendapatkannya. Halaman dari tabel pada disk masuk ke kumpulan buffer dari DBMS secara independen, tidak pernah bergabung sebelumnya, dan agar bergabung harus terjadi dengan setiap eksekusi permintaan bahkan jika data disematkan dalam kumpulan buffer. Dalam skenario ini membuat mereka kolom NULLABLE pada tabel asli akan memungkinkan mesin penyimpanan DBMS untuk menyimpannya secara efisien ketika NULL dan menghilangkan kebutuhan untuk bergabung pada pengambilan.

Bagi saya sepertinya case use Anda adalah yang terakhir dan menambahkannya sebagai NULLABLE ke tabel asli Anda adalah caranya. Tetapi seperti semua hal lain dalam desain basis data, itu tergantung, dan untuk membuat keputusan yang tepat, Anda perlu mengetahui beban kerja yang diharapkan dan tergantung pada pilihan mana. Salah satu contoh kasus penggunaan yang tepat untuk partisi vertikal adalah panel pencarian orang, di mana aplikasi Anda memiliki beberapa informasi yang sangat jarang tentang seseorang yang mungkin ingin dicari seseorang tetapi jarang dilakukan. Jika Anda memasukkan informasi itu ke tabel yang berbeda, Anda memiliki beberapa opsi kinerja yang bagus. Anda dapat menulis pencarian sehingga Anda memiliki 2 kueri - yang menggunakan informasi utama yang selalu diisi untuk mencari (seperti nama belakang atau ssn) saja, dan yang luar bergabung dengan informasi yang sangat jarang hanya ketika diminta untuk pencarian. Atau Anda dapat memanfaatkan pengoptimal DBMS jika cukup cerdas untuk mengenali set variabel host tertentu yang tidak perlu digabung dan tidak akan dijalankan, sehingga Anda hanya perlu membuat 1 kueri.

Platform DBMS apa yang Anda gunakan? Cara platform menangani penyimpanan kolom NULL, mengoptimalkan kueri Anda, serta ketersediaan dukungan kolom jarang (SQL Server memilikinya) akan memengaruhi keputusan. Pada akhirnya saya akan merekomendasikan mencoba kedua desain di lingkungan pengujian dengan data ukuran produksi dan beban kerja dan melihat mana yang lebih baik mencapai tujuan kinerja Anda.

Todd Everett
sumber
Tidak jelas bagi saya apa yang Anda maksud dengan "Namun, jika Anda akan selalu menanyakan kolom ini bersama dengan kolom di tabel asli maka partisi vertikal tidak akan masuk akal karena Anda harus selalu bergabung dengan luar untuk mendapatkannya." , Anda hanya perlu melakukan gabungan luar ketika Anda menginginkan kolom primer tersedia atau tidaknya kolom sekunder, jika tidak, Anda akan menggunakan INNER JOIN, dan hal itu bermanfaat dalam banyak kasus (mengurangi jumlah baris yang dilihat ).
jmoreno
Terima kasih atas semua bantuan di sini .. Saya benar-benar pergi dengan menambahkan bidang, tetapi setelah memikirkan ini, saya melihat bahwa saya harus memiliki beberapa tabel lain untuk mengidentifikasi semuanya dengan lebih baik. Apa yang akhirnya muncul adalah visitor visitor_visits (yang memiliki visitor_id dan berisi sumber) page_views (yang memiliki vistor_id dan visitor_visit_id) karena saya ingin tahu dengan pasti ke mana page_view dikaitkan dengan kunjungan, saya menambahkan tautan itu. Saya bergumul dengannya sebentar, tapi saya pikir itu adalah keputusan yang tepat
cgmckeever
10

Secara pribadi saya condong ke arah menambahkan kolom ke tabel yang ada. Tabel baru tidak benar-benar membelikan Anda apa pun:

  • Anda tidak benar-benar menghemat banyak ruang karena nilai-nilai NULL dalam tabel asli tidak memakan ruang apa pun, dan tabel baru membutuhkan semacam pengidentifikasi yang mengimbangi penghematan apa pun
  • pertanyaan Anda menjadi lebih kompleks ... where newcolumn is not nullmenjadi aleft outer join

Dalam tabel tunggal itu hanya berarti ukuran baris Anda dapat bervariasi dari halaman ke halaman - tetapi ini seharusnya tidak mempengaruhi banyak halaman Anda yang ada, terutama jika indeks cluster Anda berada pada kolom yang meningkat secara monoton (identitas atau tanggal / waktu).

Aaron Bertrand
sumber
Karena tabel saat ini tidak luas (berdasarkan uraian Anda) dan data ini tidak akan terlalu lebar, saya setuju.
HLGEM
4

Mengingat informasi yang Anda berikan, dan hanya dengan normalisasi umum sebagai tujuannya, saya mungkin hanya akan menambahkan kolom nullable, tetapi Anda belum memberikan informasi yang cukup tentang bagaimana data akan digunakan untuk mengetahui apa cara terbaik untuk memodelkan data aku s.

Bergantung pada bagaimana Anda benar-benar menggunakan data ini, Anda mungkin ingin mempertimbangkan model data yang berbeda. Jika Anda menempatkan data ini untuk pelaporan, Anda mungkin ingin melihat ke dalam model dimensi, yang dapat lebih efisien untuk jenis pelaporan tertentu - misalnya analisis waktu-hari bekerja dengan baik dengan pemisahan tanggal dan waktu.

Untuk menjawab pertanyaan analitik, seperti "waktu apa yang paling populer untuk kunjungan dari kampanye seperti X" atau "hari apa kampanye yang paling banyak kita lihat per jamnya", satu kolom waktu data tidak akan berfungsi sangat baik (tetapi ini bahkan dapat dibagi dalam model relasional), dan ada banyak kasus di mana Anda mungkin memperlakukan alamat IP sebagai dimensi (mungkin dengan beberapa jenis data geografi dalam kepingan salju).

Cade Roux
sumber