Pembaruan:
Lihat artikel ini di blog saya untuk strategi pengindeksan yang efisien untuk kueri Anda menggunakan kolom yang dihitung:
Ide utamanya adalah kita hanya menghitung length
bulat dan startDate
untuk rentang Anda dan kemudian mencarinya menggunakan kondisi kesetaraan (yang bagus untuk B-Tree
indeks)
Di MySQL
dan di SQL Server 2008
anda bisa menggunakan SPATIAL
indeks (R-Tree
).
Mereka sangat baik untuk kondisi seperti "pilih semua catatan dengan titik tertentu di dalam rentang catatan", yang merupakan kasus Anda.
Anda menyimpan start_date
dan end_date
sebagai awal dan akhir dari LineString
(mengubahnya menjadi UNIX
stempel waktu dari nilai numerik lain), indeks dengan SPATIAL
indeks dan cari semua LineString
s yang kotak pembatas minimumnya (MBR
) berisi nilai tanggal yang dimaksud, menggunakan MBRContains
.
Lihat entri ini di blog saya tentang cara melakukannya di MySQL
:
dan ikhtisar kinerja singkat untuk SQL Server
:
Solusi yang sama dapat diterapkan untuk mencari IP
yang diberikan terhadap rentang jaringan yang disimpan dalam database.
Tugas ini, bersama dengan kueri Anda, adalah contoh lain yang sering digunakan untuk kondisi seperti itu.
B-Tree
biasa indeks tidak bagus jika rentangnya bisa tumpang tindih.
Jika mereka tidak bisa (dan Anda tahu itu), Anda dapat menggunakan solusi brilian yang diusulkan oleh @AlexKuznetsov
Perhatikan juga bahwa kinerja kueri ini sepenuhnya bergantung pada distribusi data Anda.
Jika Anda memiliki banyak catatan di B
dan beberapa catatan di A
, Anda bisa membuat indeks pada B.dates
dan biarkan TS/CIS
di A
pergi.
Kueri ini akan selalu membaca semua baris dari A
dan akan menggunakan Index Seek
pada B.dates
dalam loop bersarang.
Jika data Anda didistribusikan sebaliknya, i. e. Anda memiliki banyak baris di A
tapi sedikit di B
, dan rentangnya umumnya pendek, maka Anda dapat mendesain ulang tabel Anda sedikit:
A
start_date interval_length
, buat indeks komposit pada A (interval_length, start_date)
dan gunakan kueri ini:
SELECT *
FROM (
SELECT DISTINCT interval_length
FROM a
) ai
CROSS JOIN
b
JOIN a
ON a.interval_length = ai.interval_length
AND a.start_date BETWEEN b.date - ai.interval_length AND b.date