Saya menggunakan MS SQL, dan saya harus menjalankan beberapa pertanyaan pada tabel yang sama dengan kriteria yang berbeda. Pada awalnya saya menjalankan setiap permintaan pada tabel asli meskipun mereka semua berbagi beberapa pemfilteran (yaitu Tanggal, status). Ini memakan banyak waktu (sekitar 2 menit).
Ada duplikat dalam baris data, dan semua indeks TIDAK BERKELAS. Saya hanya tertarik pada 4 kolom untuk kriteria saya dan hasilnya akan menampilkan hitungan saja, untuk semua pertanyaan.
kolom yang diperlukan: TABLE
, FIELD
, AFTER
, DATE
, dan ada indeks pada masing-masing DATE
dan TABLE
.
Setelah membuat tabel temp dengan hanya bidang yang saya butuhkan, turun menjadi 1:40 menit, yang masih sangat buruk.
CREATE TABLE #TEMP
(
TABLE VARCHAR(30) NULL,
FIELD VARCHAR(30) NULL,
AFTER VARCHAR(1000) NULL,
DATE DATETIME,
SORT_ID INT IDENTITY(1,1)
)
CREATE CLUSTERED INDEX IX_ADT ON #TEMP(SORT_ID)
INSERT INTO #TEMP (TABLE, FIELD, AFTER, DATE)
SELECT TABLE, FIELD, AFTER, DATE
FROM mytbl WITH (NOLOCK)
WHERE TABLE = 'OTB' AND
FIELD = 'STATUS'
Jalankan ini -> (216598 baris terpengaruh)
Karena tidak semua kueri mengandalkan rentang tanggal, saya tidak memasukkannya dalam kueri. Masalahnya adalah hanya butuh di atas 1 menit untuk memasukkan saja . Sisipan di atas memakan waktu 1:19 menit
Saya ingin menjalankan sesuatu seperti ini untuk beberapa pertanyaan:
SELECT COUNT(*) AS COUNT
FROM #TEMP
WHERE AFTER = 'R' AND
DATE >= '2014-01-01' AND
DATE <= '2015-01-01'
Ini masalah dengan penyisipan lebih dari seleksi, tetapi temp memiliki baris jauh lebih sedikit daripada tabel asli yang bisa lebih baik daripada melalui tabel beberapa kali.
Bagaimana saya bisa mengoptimalkan ini?
EDIT
Saya telah menghapus ID pengurutan, saya pikir masalahnya terutama dengan memilih dan tidak memasukkan. Itu hanya dugaan.
Saya tidak dapat membuat unik pada indeks apa pun karena tidak ada bidang atau baris yang unik.
Saya menggunakan SQL Server 2012.
Info Tabel : Ini tumpukan dan memiliki penggunaan ruang berikut:
name rows reserved data index_size unused
mytbl 24869658 9204568 KB 3017952 KB 5816232 KB 370384 KB
SELECT COUNT(*) AS COUNT FROM original_table WHERE AFTER = 'R' AND DATE >= '2014-01-01' AND DATE < '2015-01-01'
, mengapa Anda tidak mencoba mengoptimalkan masing-masing (kueri) secara terpisah? Apakah Anda tidak diizinkan menambahkan indeks ke tabel?TABLE
danFIELD
dari#temp
tabel (semua baris memilikiTABLE = 'OTB' AND FIELD = 'STATUS'
untuk tabel temp spesifik setelah semua.)CREATE TABLE
pernyataan). Pemungutan suara turun karena pertanyaannya tidak jelas.Jawaban:
Pertanyaannya terutama tentang bagaimana mengoptimalkan pernyataan pilih:
Menghapus proyeksi yang berlebihan dan menambahkan
dbo
skema yang diduga :Tanpa indeks seperti
([TABLE],[FIELD]) INCLUDE ([AFTER],[DATE])
SQL Server memiliki dua opsi utama:[TABLE] = 'OTB'
dan[FIELD] = 'STATUS'
(menggunakanIDX6
), kemudian lakukan pencarian tumpukan (RID) per baris untuk mengambil[AFTER]
dan[DATE]
kolom.Apakah optimizer memilih heap scan atau pencarian indeks dengan pencarian RID tergantung pada selektivitas perkiraan
[TABLE] = 'OTB'
dan[FIELD] = 'STATUS'
predikat. Periksa untuk melihat apakah perkiraan jumlah baris dari pencarian cocok dengan kenyataan. Jika tidak, perbarui statistik Anda. Uji kueri dengan petunjuk tabel yang memaksa penggunaan indeks, jika kondisi itu cukup selektif . Jika pengoptimal saat ini memilih pencarian indeks, uji kinerja denganINDEX(0)
atauFORCESCAN
petunjuk untuk memindai tumpukan.Selain itu, Anda dapat sedikit meningkatkan pemindaian tumpukan dengan menghapus beberapa ruang yang tidak digunakan (370MB). Dalam SQL Server 2008 ini dapat dilakukan dengan membangun kembali heap. Ruang yang tidak terpakai dalam tumpukan sering hasil dari penghapusan yang dilakukan tanpa kunci meja diambil (tanpa kunci meja, halaman kosong tidak dialokasikan dari tumpukan). Tabel yang sering mengalami penghapusan seringkali lebih baik disimpan sebagai tabel berkerumun karena alasan ini.
Kinerja pemindaian tumpukan tergantung pada seberapa banyak tabel disimpan dalam memori, berapa banyak harus dibaca dari disk, seberapa penuh halaman, kecepatan penyimpanan persisten, apakah pemindaian I / O atau terikat CPU ( paralelisme dapat membantu).
Jika kinerja masih tidak dapat diterima setelah Anda menyelidiki semua hal di atas, cobalah membuat case untuk indeks baru. Jika tersedia di versi SQL Server Anda, kemungkinan indeks yang difilter untuk kueri yang diberikan adalah:
Juga pertimbangkan kompresi indeks, jika tersedia dan bermanfaat. Tanpa semacam indeks baru, relatif sedikit yang dapat Anda lakukan untuk meningkatkan kinerja kueri yang diberikan.
sumber
IDX6 nonclustered located on PRIMARY TABLE, FIELD
. Mungkin ini akan mengubah hal-hal yang Anda sebutkan?Saya pikir ada alasan untuk mengubah indeks di sini karena:
Ini juga akan menjadi kasus penggunaan yang baik untuk indeks columnstore non-clustered diperkenalkan di SQL Server 2012, yaitu meringkas / mengagregasi beberapa kolom pada tabel besar dengan banyak kolom.
Meskipun indeks ini memiliki efek samping dari membuat tabel hanya-baca (dengan pengecualian beralih partisi), mereka dapat mengubah kinerja kueri agregat di bawah kondisi yang tepat. Aspek read-only dapat dikelola, baik dengan menjatuhkan dan membuat ulang indeks atau data partisi sederhana beralih ke tabel.
Saya menyiapkan rig uji sederhana untuk meniru pengaturan Anda, dan melihat peningkatan kinerja yang baik:
Hasil saya, 6 detik v 0,08 detik:
Ringkasnya, coba dan bangun kasing dengan atasan Anda agar indeksnya diubah atau setidaknya buat semacam proses semalaman di mana catatan-catatan ini diukir menjadi tabel / basis data pelaporan hanya-baca tempat Anda dapat melakukan pekerjaan Anda, dan menambahkan pengindeksan sesuai untuk beban kerja itu.
sumber