Saya menyimpan data sensor dalam tabel Nilai Sensor . Tabel dan kunci utama adalah sebagai berikut:
CREATE TABLE [dbo].[SensorValues](
[DeviceId] [int] NOT NULL,
[SensorId] [int] NOT NULL,
[SensorValue] [int] NOT NULL,
[Date] [int] NOT NULL,
CONSTRAINT [PK_SensorValues] PRIMARY KEY CLUSTERED
(
[DeviceId] ASC,
[SensorId] ASC,
[Date] DESC
) WITH (
FILLFACTOR=75,
DATA_COMPRESSION = PAGE,
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON)
ON [MyPartitioningScheme]([Date])
Namun, ketika saya memilih nilai sensor yang valid untuk waktu tertentu, rencana eksekusi memberitahu saya itu sedang melakukan semacam. Mengapa demikian?
Saya akan berpikir bahwa karena saya menyimpan nilai yang diurutkan berdasarkan kolom Date, pengurutan tidak akan terjadi. Atau apakah itu karena indeks tidak hanya diurutkan berdasarkan kolom Tanggal, artinya tidak dapat berasumsi bahwa set hasil diurutkan?
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
ORDER BY Date DESC
Sunting: Bisakah saya melakukan ini?
Karena tabel diurutkan DeviceId, SensorId, Date dan saya melakukan SELECT menentukan hanya satu DeviceId dan satu SensorId , output yang ditetapkan harus sudah diurutkan berdasarkan Date DESC . Jadi saya bertanya-tanya apakah pertanyaan berikut akan menghasilkan hasil yang sama dalam semua kasus?
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
Menurut @Catcall di bawah ini, urutan pengurutan tidak sama dengan urutan penyimpanan. Yaitu kita tidak dapat mengasumsikan bahwa nilai yang dikembalikan sudah dalam urutan diurutkan.
Sunting: Saya sudah mencoba solusi CROSS APPLY ini, tidak berhasil
@ Martin Smith menyarankan saya akan mencoba LUAR MENERAPKAN hasil saya terhadap partisi. Saya menemukan posting blog ( Indeks non-clustered disejajarkan pada tabel dipartisi ) menggambarkan masalah yang sama dan mencoba solusi yang agak mirip dengan apa yang disarankan Smith. Namun, tidak beruntung di sini, waktu eksekusi setara dengan solusi asli saya.
WITH Boundaries(boundary_id)
AS
(
SELECT boundary_id
FROM sys.partition_functions pf
JOIN sys.partition_range_values prf ON pf.function_id = prf.function_id
WHERE pf.name = 'PF'
AND prf.value <= 1339225010
UNION ALL
SELECT max(boundary_id) + 1
FROM sys.partition_functions pf
JOIN sys.partition_range_values prf ON pf.function_id = prf.function_id
WHERE pf.name = 'PF'
AND prf.value <= 1339225010
),
Top1(SensorValue)
AS
(
SELECT TOP 1 d.SensorValue
FROM Boundaries b
CROSS APPLY
(
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND "Date" < 1339225010
AND $Partition.PF(Date) = b.boundary_id
ORDER BY Date DESC
) d
ORDER BY d.Date DESC
)
SELECT SensorValue
FROM Top1
Jawaban:
Untuk tabel yang tidak dipartisi saya mendapatkan paket berikut
Ada satu predikat pencarian
Seek Keys[1]: Prefix: DeviceId, SensorId = (3819, 53), Start: Date < 1339225010
.Berarti SQL Server dapat melakukan pencarian kesetaraan pada dua kolom pertama dan kemudian mulai mencari rentang mulai dari
1339225010
dan dipesanFORWARD
(karena indeks didefinisikan dengan[Date] DESC
)The
TOP
Operator akan berhenti meminta lebih baris dari mencari setelah baris pertama dipancarkan.Ketika saya membuat skema dan fungsi partisi
Dan isi tabel dengan data berikut
Paket SQL Server 2008 terlihat sebagai berikut.
Jumlah baris aktual yang dipancarkan dari pencarian adalah
500
. Rencana menunjukkan mencari predikatMengindikasikan itu menggunakan pendekatan skip scan yang dijelaskan di sini
Paket ini adalah paket serial dan jadi untuk permintaan khusus Anda memilikinya tampaknya jika SQL Server memastikan bahwa ia memproses partisi dalam urutan menurun dari
date
paket asli denganTOP
masih akan bekerja dan bisa berhenti memproses setelah baris pencocokan pertama adalah ditemukan daripada melanjutkan dan menghasilkan 499 sisa pertandingan.Sebenarnya rencana tahun 2005 sepertinya mengambil pendekatan itu
Saya tidak yakin apakah itu lurus ke depan untuk mendapatkan rencana yang sama pada 2008 atau mungkin perlu
OUTER APPLY
onsys.partition_range_values
untuk mensimulasikannya.sumber
Banyak orang percaya bahwa indeks berkerumun menjamin urutan pengurutan pada output. Tapi bukan itu yang dilakukannya; itu menjamin pesanan penyimpanan pada disk.
Lihat, misalnya, posting blog ini , dan diskusi yang lebih panjang ini .
sumber
Saya berspekulasi bahwa SORT diperlukan karena rencana paralel. Saya mendasarkan ini pada beberapa artikel blog redup dan jauh: tapi saya menemukan ini di MSDN yang mungkin atau mungkin tidak membenarkan ini
Jadi, coba dengan MAXDOP 1 dan lihat apa yang terjadi ...
Juga mengisyaratkan di dalam posting blog kiwi @sql di Talk Sederhana di bawah "Operator Exchange" saya pikir. Dan "ketergantungan DOP" di sini
sumber
date
sebelumnya. Sekarang saya telah dan sepertinya mempartisi adalah penyebab 2005 mungkin berperilaku lebih baik untuk permintaan khusus ini.Pada dasarnya Anda benar - karena kunci utama dalam urutan "DeviceId, SensorId, Date", data dalam kunci tersebut tidak diurutkan berdasarkan tanggal, jadi tidak dapat digunakan. Jika kunci Anda berada dalam urutan berbeda "Date, DeviceId, SensorId", maka data dalam kunci tersebut akan diurutkan berdasarkan tanggal, sehingga dapat digunakan ...
sumber