Saya memiliki tampilan indeks berikut yang didefinisikan dalam SQL Server 2008 (Anda dapat mengunduh skema kerja dari intisari untuk tujuan pengujian):
CREATE VIEW dbo.balances
WITH SCHEMABINDING
AS
SELECT
user_id
, currency_id
, SUM(transaction_amount) AS balance_amount
, COUNT_BIG(*) AS transaction_count
FROM dbo.transactions
GROUP BY
user_id
, currency_id
;
GO
CREATE UNIQUE CLUSTERED INDEX UQ_balances_user_id_currency_id
ON dbo.balances (
user_id
, currency_id
);
GO
user_id
,, currency_id
dan transaction_amount
semuanya didefinisikan sebagai NOT NULL
kolom dalam dbo.transactions
. Namun, ketika saya melihat definisi tampilan di Object Explorer Management Studio, itu menandai kedua balance_amount
dan transaction_count
sebagai NULL
-able kolom dalam tampilan.
Saya telah melihat beberapa diskusi, yang ini adalah yang paling relevan dari mereka, yang menyarankan beberapa pengocokan fungsi dapat membantu SQL Server mengenali bahwa kolom tampilan selalu NOT NULL
. Namun, tidak ada pengocokan seperti itu dalam kasus saya, karena ekspresi pada fungsi agregat (misalnya a ISNULL()
atas SUM()
) tidak diperbolehkan dalam tampilan yang diindeks.
Apakah ada cara saya dapat membantu SQL Server mengenali itu
balance_amount
dantransaction_count
dapatNOT NULL
digunakan?Jika tidak, haruskah saya memiliki keprihatinan tentang kolom-kolom ini yang secara keliru diidentifikasi sebagai
NULL
-able?Dua masalah yang bisa saya pikirkan adalah:
- Setiap objek aplikasi yang dipetakan ke tampilan saldo mendapatkan definisi saldo yang salah.
- Dalam kasus yang sangat terbatas, pengoptimalan tertentu tidak tersedia untuk Pengoptimal Kueri karena tidak memiliki jaminan dari pandangan bahwa kedua kolom ini
NOT NULL
.
Apakah salah satu dari masalah ini merupakan masalah besar? Apakah ada masalah lain yang harus saya ingat?
sumber
Jawaban:
Tampak bagi saya bahwa SQL Server memiliki asumsi selimut bahwa agregat dapat menghasilkan
null
bahkan jika bidang yang dioperasikannya adalahnot null
. Ini jelas benar dalam kasus-kasus tertentu:Dan juga benar dalam versi umum
group by
sukacube
Case uji yang lebih sederhana ini mengilustrasikan poin bahwa setiap agregat diartikan sebagai nullable:
IMO ini adalah batasan (walaupun kecil) dari SQL Server - beberapa RDBMS lain memungkinkan pembuatan batasan tertentu pada pandangan yang tidak ditegakkan dan ada hanya untuk memberikan petunjuk kepada pengoptimal, meskipun saya pikir 'keunikan' lebih cenderung untuk membantu dalam menghasilkan rencana permintaan yang baik daripada 'nullability'
Jika nullability kolom itu penting, mungkin untuk digunakan dengan ORM, pertimbangkan untuk membungkus tampilan yang diindeks di tampilan lain yang hanya menjamin non-nullability menggunakan
ISNULL
:sumber
Saya tidak berpikir ada cara Anda dapat memaksa SQL Server untuk mengenali kolom-kolom ini sebagai tidak dapat dibatalkan, meskipun jelas tidak. Anda dapat mencoba mengubah urutan bagaimana Anda mendefinisikan
ISNULL
/COALESCE
sekitar ekspresi di dalamSUM()
, misalnya, tetapi itu tidak akan membantu.Saya juga tidak percaya ada optimasi yang akan Anda lewatkan - kolom-kolom tersebut saat ini tidak diindeks, jadi tidak seperti optimizer dapat memilih metode akses yang berbeda untuk menentukan, katakanlah, semua
balance_amount
nilai> 10000. Ada mungkin situasi di mana jika Anda membuat indeks non-cluster di salah satu kolom Anda mungkin mendapatkan perkiraan sedikit lebih baik daripada jika indeks tidak ada, tetapi ini tidak ada hubungannya dengan nullability.Saya tidak akan terlalu khawatir tentang ini dari perspektif kinerja. Saya kembali dan melihat sekelompok tampilan indeks yang telah saya buat selama bertahun-tahun dan kolom agregasi ini semuanya dapat dibatalkan. Mereka melakukan dengan baik.
Sejauh pemetaan objek berjalan, sekali lagi, saya tidak akan terlalu khawatir tentang hal itu. Karena aplikasi tidak dapat memperbarui tampilan yang diindeks, tidak masalah jika menurutnya itu
balance_amount
bisanull
. Itu tidak akan pernah menerimanull
, dan tidak dapat mencoba untuk menulisnull
, jadi<shrug>
.sumber