Pikir ini diselesaikan dengan tautan di bawah ini - pekerjaan di sekitar bekerja - tetapi tambalan tidak. Bekerja dengan dukungan Microsoft untuk menyelesaikan.
http://support.microsoft.com/kb/2606883
Ok jadi saya punya masalah yang ingin saya buang ke StackOverflow untuk melihat apakah ada yang punya ide.
Perhatikan ini dengan SQL Server 2008 R2
Masalah: Menghapus 3000 catatan dari tabel dengan 15000 catatan membutuhkan waktu 3-4 menit saat pemicu diaktifkan dan hanya 3-5 detik saat pemicu dinonaktifkan.
Pengaturan meja
Dua tabel akan kita sebut Utama dan Sekunder. Sekunder berisi rekaman item yang ingin saya hapus jadi ketika saya melakukan hapus saya gabung ke tabel Sekunder. Proses berjalan sebelum pernyataan hapus untuk mengisi tabel sekunder dengan catatan yang akan dihapus.
Hapus Pernyataan:
DELETE FROM MAIN
WHERE ID IN (
SELECT Secondary.ValueInt1
FROM Secondary
WHERE SECONDARY.GUID = '9FFD2C8DD3864EA7B78DA22B2ED572D7'
);
Tabel ini memiliki banyak kolom dan sekitar 14 Indeks NC berbeda. Saya mencoba banyak hal yang berbeda sebelum saya menentukan pemicunya adalah masalahnya.
- Aktifkan penguncian halaman (kami telah dimatikan secara default)
- Statistik Berkumpul Secara Manual
- Statistik pengumpulan otomatis dinonaktifkan
- Kesehatan dan fragmentasi Indeks Terverifikasi
- Menjatuhkan indeks berkerumun dari tabel
- Memeriksa rencana pelaksanaan (tidak ada yang menunjukkan indeks yang hilang dan biayanya 70 persen terhadap penghapusan aktual dengan sekitar 28 persen untuk gabungan / penggabungan catatan
Pemicu
Tabel memiliki 3 pemicu (masing-masing untuk menyisipkan, memperbarui, dan menghapus operasi). Saya memodifikasi kode untuk memicu hapus untuk kembali, lalu untuk memilih satu untuk melihat berapa kali dipecat. Hanya menyala satu kali selama seluruh operasi (seperti yang diharapkan).
ALTER TRIGGER [dbo].[TR_MAIN_RD] ON [dbo].[MAIN]
AFTER DELETE
AS
SELECT 1
RETURN
Untuk Rekap
- Dengan Pemicu pada - pernyataan dibutuhkan 3-4 menit untuk menyelesaikan
- Dengan Trigger off - statement akan selesai dalam 3-5 detik
Adakah yang tahu mengapa?
Perhatikan juga - tidak ingin mengubah arsitektur ini, menambahkan indeks hapus, dll. Sebagai solusi. Tabel ini adalah bagian utama untuk beberapa operasi data utama dan kami harus mengubah dan menyetelnya (indeks, penguncian halaman, dll.) Untuk memungkinkan operasi konkurensi utama untuk bekerja tanpa deadlock.
Berikut adalah rencana eksekusi xml (nama diubah untuk melindungi yang tidak bersalah)
<?xml version="1.0" encoding="utf-16"?>
<ShowPlanXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.1" Build="10.50.1790.0" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
<BatchSequence>
<Batch>
<Statements>
<StmtSimple StatementCompId="1" StatementEstRows="185.624" StatementId="1" StatementOptmLevel="FULL" StatementOptmEarlyAbortReason="GoodEnoughPlanFound" StatementSubTreeCost="0.42706" StatementText="DELETE FROM MAIN WHERE ID IN (SELECT Secondary.ValueInt1 FROM Secondary WHERE Secondary.SetTMGUID = '9DDD2C8DD3864EA7B78DA22B2ED572D7')" StatementType="DELETE" QueryHash="0xAEA68D887C4092A1" QueryPlanHash="0x78164F2EEF16B857">
<StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="false" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" />
<QueryPlan CachedPlanSize="48" CompileTime="20" CompileCPU="20" CompileMemory="520">
<RelOp AvgRowSize="9" EstimateCPU="0.00259874" EstimateIO="0.296614" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="185.624" LogicalOp="Delete" NodeId="0" Parallel="false" PhysicalOp="Clustered Index Delete" EstimatedTotalSubtreeCost="0.42706">
<OutputList />
<Update WithUnorderedPrefetch="true" DMLRequestSort="false">
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[IX_MAIN_02]" IndexKind="Clustered" />
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[PK_MAIN_ID]" IndexKind="NonClustered" />
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[UK_MAIN_01]" IndexKind="NonClustered" />
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[IX_MAIN_03]" IndexKind="NonClustered" />
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[IX_MAIN_04]" IndexKind="NonClustered" />
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[IX_MAIN_05]" IndexKind="NonClustered" />
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[IX_MAIN_06]" IndexKind="NonClustered" />
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[IX_MAIN_07]" IndexKind="NonClustered" />
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[IX_MAIN_08]" IndexKind="NonClustered" />
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[IX_MAIN_09]" IndexKind="NonClustered" />
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[IX_MAIN_10]" IndexKind="NonClustered" />
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[IX_MAIN_11]" IndexKind="NonClustered" />
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[UK_MAIN_12]" IndexKind="NonClustered" />
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[IX_MAIN_13]" IndexKind="NonClustered" />
<RelOp AvgRowSize="15" EstimateCPU="1.85624E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="185.624" LogicalOp="Top" NodeId="2" Parallel="false" PhysicalOp="Top" EstimatedTotalSubtreeCost="0.127848">
<OutputList>
<ColumnReference Column="Uniq1002" />
<ColumnReference Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Column="RelationshipID" />
</OutputList>
<Top RowCount="true" IsPercent="false" WithTies="false">
<TopExpression>
<ScalarOperator ScalarString="(0)">
<Const ConstValue="(0)" />
</ScalarOperator>
</TopExpression>
<RelOp AvgRowSize="15" EstimateCPU="0.0458347" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="185.624" LogicalOp="Left Semi Join" NodeId="3" Parallel="false" PhysicalOp="Merge Join" EstimatedTotalSubtreeCost="0.12783">
<OutputList>
<ColumnReference Column="Uniq1002" />
<ColumnReference Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Column="RelationshipID" />
</OutputList>
<Merge ManyToMany="false">
<InnerSideJoinColumns>
<ColumnReference Database="[MyDatabase]" Schema="[dbo]" Table="[Secondary]" Column="ValueInt1" />
</InnerSideJoinColumns>
<OuterSideJoinColumns>
<ColumnReference Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Column="ID" />
</OuterSideJoinColumns>
<Residual>
<ScalarOperator ScalarString="[MyDatabase].[dbo].[MAIN].[ID]=[MyDatabase].[dbo].[Secondary].[ValueInt1]">
<Compare CompareOp="EQ">
<ScalarOperator>
<Identifier>
<ColumnReference Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Column="ID" />
</Identifier>
</ScalarOperator>
<ScalarOperator>
<Identifier>
<ColumnReference Database="[MyDatabase]" Schema="[dbo]" Table="[Secondary]" Column="ValueInt1" />
</Identifier>
</ScalarOperator>
</Compare>
</ScalarOperator>
</Residual>
<RelOp AvgRowSize="19" EstimateCPU="0.0174567" EstimateIO="0.0305324" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="15727" LogicalOp="Index Scan" NodeId="4" Parallel="false" PhysicalOp="Index Scan" EstimatedTotalSubtreeCost="0.0479891" TableCardinality="15727">
<OutputList>
<ColumnReference Column="Uniq1002" />
<ColumnReference Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Column="ID" />
<ColumnReference Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Column="RelationshipID" />
</OutputList>
<IndexScan Ordered="true" ScanDirection="FORWARD" ForcedIndex="false" ForceSeek="false" NoExpandHint="false">
<DefinedValues>
<DefinedValue>
<ColumnReference Column="Uniq1002" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Column="ID" />
</DefinedValue>
<DefinedValue>
<ColumnReference Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Column="RelationshipID" />
</DefinedValue>
</DefinedValues>
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[MAIN]" Index="[PK_MAIN_ID]" IndexKind="NonClustered" />
</IndexScan>
</RelOp>
<RelOp AvgRowSize="11" EstimateCPU="0.00392288" EstimateIO="0.03008" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="3423.53" LogicalOp="Index Seek" NodeId="5" Parallel="false" PhysicalOp="Index Seek" EstimatedTotalSubtreeCost="0.0340029" TableCardinality="171775">
<OutputList>
<ColumnReference Database="[MyDatabase]" Schema="[dbo]" Table="[Secondary]" Column="ValueInt1" />
</OutputList>
<IndexScan Ordered="true" ScanDirection="FORWARD" ForcedIndex="false" ForceSeek="false" NoExpandHint="false">
<DefinedValues>
<DefinedValue>
<ColumnReference Database="[MyDatabase]" Schema="[dbo]" Table="[Secondary]" Column="ValueInt1" />
</DefinedValue>
</DefinedValues>
<Object Database="[MyDatabase]" Schema="[dbo]" Table="[Secondary]" Index="[IX_Secondary_01]" IndexKind="NonClustered" />
<SeekPredicates>
<SeekPredicateNew>
<SeekKeys>
<Prefix ScanType="EQ">
<RangeColumns>
<ColumnReference Database="[MyDatabase]" Schema="[dbo]" Table="[Secondary]" Column="SetTMGUID" />
</RangeColumns>
<RangeExpressions>
<ScalarOperator ScalarString="'9DDD2C8DD3864EA7B78DA22B2ED572D7'">
<Const ConstValue="'9DDD2C8DD3864EA7B78DA22B2ED572D7'" />
</ScalarOperator>
</RangeExpressions>
</Prefix>
</SeekKeys>
</SeekPredicateNew>
</SeekPredicates>
</IndexScan>
</RelOp>
</Merge>
</RelOp>
</Top>
</RelOp>
</Update>
</RelOp>
</QueryPlan>
</StmtSimple>
</Statements>
</Batch>
</BatchSequence>
</ShowPlanXML>
Nah di sini adalah tanggapan resmi dari Microsoft ... yang saya pikir merupakan cacat desain utama.
11/14/2011 - Tanggapan resmi telah berubah. Mereka tidak menggunakan log transaksi seperti yang dinyatakan sebelumnya. Menggunakan toko internal (level baris) untuk menyalin data yang diubah ke. Mereka masih belum bisa memastikan mengapa ini butuh waktu lama.
Kami memutuskan untuk menggunakan Alih-alih pemicu sebagai pengganti setelah menghapus pemicu.
Bagian SETELAH dari pemicu menyebabkan kita harus membaca log transaksi setelah penghapusan selesai dan membangun pemicu yang dimasukkan / dihapus tabel. Di sinilah kami menghabiskan banyak waktu dan dirancang untuk bagian SETELAH pemicunya. BUKAN pemicu akan mencegah perilaku memindai log transaksi dan membangun tabel yang dimasukkan / dihapus. Juga, seperti yang diamati bahwa hal-hal jauh lebih cepat jika kita drop semua kolom dengan nvarchar (maks), yang masuk akal karena fakta bahwa itu dianggap data LOB. Silakan baca artikel di bawah ini untuk informasi lebih lanjut mengenai data In-Row:
http://msdn.microsoft.com/en-us/library/ms189087.aspx
Ringkasan: SETELAH pemicu memerlukan pemindaian kembali melalui log transaksi setelah penghapusan selesai maka kita harus membuat dan memasukkan / menghapus tabel yang membutuhkan lebih banyak penggunaan log transaksi dan waktu.
Jadi sebagai rencana aksi, inilah yang kami sarankan saat ini:
sumber
Menurut rencana semuanya berjalan dengan benar. Anda dapat mencoba menulis penghapusan sebagai GABUNG bukannya IN yang akan memberi Anda rencana yang berbeda.
Saya tidak yakin berapa banyak yang akan membantu. Ketika penghapusan berjalan dengan pemicu di atas meja, apa jenis tunggu untuk sesi melakukan penghapusan?
sumber