Arresto anomalo dell'istanza di SQL Server durante il casting in numerico


20

Mentre lavoravo con C # Entity Framework ho notato un arresto anomalo della mia istanza di SQL Server.

Sono stato in grado di rintracciarlo fino a questa affermazione:

SELECT * FROM dbo.[TestTable]
where mpnr in (1099059904,
1038139906,
1048119902,
1045119902,
1002109903,
1117109910,
1111149902,
1063149902,
1117159902,
1116109904,
1105079905,
1012079906,
1129129904,
1103059905,
1065059905,
1091059906,
1110149904,
1129149903,
1083029905,
1080139904,
1076109903,
1010019902,
1058019902,
1060019903,
1053019902,
1030089902,
1018149902,
1077149902,
1010109901,
1011109901,
1000119902,
1023049903,
1107119909,
1108119909,
1106119909)

La tabella è simile alla seguente:

CREATE TABLE dbo.[TestTable]([MPNR] [numeric](9, 0) NOT NULL)

L'incidente si verifica ogni volta che inizio la query. Se riduco il numero di valori all'interno della INclausola, funziona. (Ovviamente non restituisce righe.)

Sono consapevole che i valori nella INclausola sono numeri di 10 cifre e la colonna ha solo 9 cifre, ma ciò non dovrebbe comportare un arresto anomalo dell'intera istanza di SQL Server.

La mia versione di SQL Server è 2008 R2 su un Windows Server 2003 a 32 bit.

È un bug noto? Esiste una patch per SQL Server?


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Paul White dice GoFundMonica

Risposte:


20

Sono stato in grado di riprogrammare su R1 SP3 2008 10.00.5512 del 2008, ma l'installazione dell'ultima CU (14) l'ha risolto.

Esaminando i bug corretti nelle versioni intermedie sembra che sia necessario eseguire l'aggiornamento a una build che include la seguente correzione.

Accedere alla violazione quando si esegue una query che contiene molti valori costanti in una clausola IN in SQL Server 2008 o in SQL Server 2012

Dato che sei su 2008 R2 avrai bisogno di almeno CU 9 per SP1 o CU 5 per SP2.

La descrizione dei sintomi è piuttosto breve ma menziona tipi di dati non corrispondenti

Quando si esegue una query che contiene molti valori costanti in una clausola IN in Microsoft SQL Server 2008, Microsoft SQL Server 2012 o in Microsoft SQL Server 2008 R2, potrebbe verificarsi una violazione di accesso.

Nota Affinché il problema si verifichi, le costanti nella clausola IN non possono corrispondere esattamente al tipo di dati della colonna.

Non definisce "molti". Dal test che ho fatto sospetto che questo possa significare "20 o più" in quanto questo sembra essere il punto di interruzione tra due diversi metodi di stima della cardinalità.

L'incidente si stava verificando all'interno di un paio di metodi chiamati CScaOp_In::FCalcSelectivity()con nomi come LoadHistogramFromXVariantArray()e CInMemHistogram::FJoin() -> WalkHistograms().

Per 19 o meno voci distinte nell'elenco, questi metodi non venivano affatto richiamati. Un simile bug di SQL Sever 2000 menziona anche questo punto di interruzione come significativo.

Popolazione di una tabella di test con 100.000 righe di dati di test casuali con valori compresi tra 0 e 1047 e un istogramma che inizia come segue

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
|            0 |          0 |     104 |                   0 | 1              |
|            8 |        672 |     118 |                   7 | 96             |
|           13 |        350 |     118 |                   4 | 87.5           |
|           18 |        395 |     107 |                   4 | 98.75          |
|           23 |        384 |      86 |                   4 | 96             |
|           28 |        371 |      85 |                   4 | 92.75          |
+--------------+------------+---------+---------------------+----------------+

La domanda

SELECT * FROM dbo.[TestTable]
where mpnr in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19)
option (maxdop 1)

Mostra le file stimate del 1856.

Questo è esattamente ciò che ci si aspetterebbe ottenendo le righe stimate per i 19 predicati di uguaglianza individualmente e sommandoli insieme.

+-------+----------------+-------+
| 1-7   | AVG_RANGE_ROWS | 96    |
| 8     | EQ_ROWS        | 118   |
| 9-12  | AVG_RANGE_ROWS | 87.5  |
| 13    | EQ_ROWS        | 118   |
| 14-17 | AVG_RANGE_ROWS | 98.75 |
| 18    | EQ_ROWS        | 107   |
| 19    | AVG_RANGE_ROWS | 96    |
+-------+----------------+-------+

7*96 + 118 + 4*87.5 + 118 + 4*98.75 + 107 + 1*96 = 1856

La formula non funziona più dopo 20essere stata aggiunta all'elenco in (Righe stimate 1902.75anziché che ne verrebbe generata l' 1952aggiunta di un'altra 96al totale).

BETWEEN sembra usare ancora un altro metodo per calcolare le stime di cardinalità.

where mpnr BETWEEN 1 AND 20stima solo 1829,6 righe. Non ho idea di come derivi dall'istogramma mostrato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.