2010-01-26 8 views
16

Ich habe CLR-Speicher-Prozeduren jetzt für eine Weile im SQL-Server verwendet, aber ich frage mich immer noch, welche die besten Situationen sind, um sie zu verwenden.Was sind gute Probleme zu lösen mit CLR gespeicherten Procs?

MSDN bietet einige Richtlinien für die Verwendung wie schwere Zeichenfolge (Regex) oder T-SQL ersetzen, die viele Tabellenvariablen und Cursor deklariert. Ich bin gespannt, welche Probleme SO-Benutzer mit CLR-gespeicherten Procs und Beispielen/Benchmarks lösen.

Zum Beispiel habe ich CLR gespeicherte Procs + SSRS gefunden, um eine gute Möglichkeit, Daten Manipulation Logik aus SSRS und aus T-SQL, und in verwalteten Code, der einfacher zu lesen und zu manipulieren ist.

Antwort

23

Viele Probleme erfordern Denormalisierung und/oder sequentielle Operationen können von der CLR außergewöhnlich gut behandelt werden und verwendet werden können die Leistung erheblich zu verbessern, ohne die Benutzerfreundlichkeit auf dem SQL-Ende zu opfern (viel). Anstatt sich ausschließlich auf set-basierte oder iterative Operationen zu verlassen, können Sie einen hybriden Ansatz wählen, eine Set-basierte Lösung für die großen Transporte verwenden und zu einem iterativen Modell für die engen Schleifen wechseln.

Die integrierten Typen hierarchyid und Geospatial (d. H. geography) in SQL Server 2008 sind gute Beispiele für das Denormalisierungsproblem. Beide enthalten eine (fast) beliebig große Menge an Daten, die schwer zu normalisieren sind, ohne die Leistung zu beeinträchtigen - Sie müssten Rekursion oder Cursor verwenden, um sinnvoll mit ihnen zu arbeiten, oder Sie verwenden ein Ratten-Nest aus Triggern und/oder geplanten Aufgaben Pflegen Sie eine Denormalisierungstabelle.

Ein anderes Problem, das ich mit CLR-Typen gelöst habe, ist die Inline-Komprimierung. Dies klingt vielleicht nach einer sinnlosen oder akademischen Übung, aber wenn Ihre vollständig normalisierten Daten in Terabytes vorstoßen, bedeutet eine Reduzierung der Größe um 80-90% eine Menge. SQL hat jetzt eine eigene integrierte Komprimierung und SQL 2005 hatte Vardecimal, und das sind auch gute Tools, aber ein domänenbewusster "Minimierungs" -Algorithmus kann sowohl hinsichtlich der CPU-Last als auch der Komprimierungsrate um ein Vielfaches effizienter sein. Natürlich gilt das nicht für jedes Problem, aber für einige.

Noch ein anderes sehr häufiges Problem, das oft auf dieser Seite gefunden wird, ist das Erzeugen einer Sequenz im laufenden Betrieb - zum Beispiel eine Folge aufeinanderfolgender Daten.Gängige Lösungen sind rekursive CTEs, statische Sequenztabellen und die wenig bekannten spt_values Tabellen, aber eine einfache CLR UDF ist besser als alle anderen und bietet viel mehr Flexibilität.

Zuletzt auf meiner Liste: Benutzerdefinierte Streaming-Aggregate sind auch sehr nützlich, besonders für alles, was mit Statistiken zu tun hat. Es gibt einige Dinge, die Sie einfach nicht aus den integrierten SQL-Aggregaten erstellen können, wie z. B. Medianwerte, gewichtete gleitende Durchschnitte usw. UDAs können auch mehrere Argumente annehmen, so dass Sie sie parametrisieren können; Technisch gesehen ist ein Aggregat nicht garantiert, Daten in einer bestimmten Reihenfolge in der aktuellen Version von SQL Server zu empfangen, aber Sie können diese Einschränkung umgehen, indem Sie ein ROW_NUMBER als zusätzliches Argument eingeben und damit nahezu jede Fensterfunktion implementieren (have das Aggregat spuckt einen UDT aus, der dann in eine Tabelle umgewandelt werden kann.

Es ist wirklich sehr frustrierend, wie wenige Beispiele wirklich nützliche SQL-CLR-Anwendungen gibt; Suchen Sie auf Google und Sie erhalten 10 Millionen Ergebnisse, jedes einzelne von ihnen für einige alberne String-Verkettung oder Regex. Diese sind nützlich, aber nehmen Sie sich ein paar Minuten Zeit, um etwas über SQL-UDTs und UDAs zu erfahren, und Sie werden sehen, dass sie in Ihren eigenen Anwendungen viel genutzt werden. Gehen Sie natürlich nicht durcheinander - denken Sie sorgfältig darüber nach, ob es eine bessere Lösung in reinem SQL gibt - aber lassen Sie sie auch nicht außer Acht. Hier

+2

Dies ist einer der informativsten Beiträge, die ich je gelesen habe. Vielen Dank. –

+0

+1 sehr schön setzen –

5

String-Manipulation - die Suche nach regulären Ausdrücken ist ein Klassiker. Sehr einfach in CLR zu veröffentlichen, sehr schwierig in T-SQL zu tun.

Weitere Informationen zur Implementierung und einen Mikro-Benchmark finden Sie unter this link (SQLCLR is only 47 milliseconds compared to 6.187 seconds for the T-SQL UDF).

5

String Manipulation (Regexes) wurde bereits erwähnt, aber auch DateTime Arithmetik, und natürlich eine andere Biggie - Aufruf externer Web Services.

+0

Hey Marc, kannst du ein Beispiel für ein Problem nennen, das du durch Zugriff auf externe Webdienste in einem CLR-Prozess lösen würdest? +1 für die Nützlichkeit sicher. –

+0

Viele Dinge - z.B. Die aktuellen Wechselkurse erhalten, aktuelle Aktieninformationen und vieles mehr erhalten. –

2
  • Benutzerdefinierte Aggregate
  • String-Manipulation
  • Benutzerdefinierte Datentypen

ehrlich zu sein, ich nur String-Handling sehen, die Spaltung CSVs in Zeilen umfasst.

Ich würde alles in Betracht ziehen, was mehr als die Standard-Vertrauensstufe außerhalb der Grenzen benötigt, es sei denn, ich war ein DBA, der Sachen vom Typ DBA macht.

Von MSDN mit RegEx und RSS-Feed Beispiele: Using CLR Integration in SQL Server 2005

3

ist ein Beispiel für etwas, das ich verwendet CLR Procs für das ich dachte, war ordentlich:

Timed Daten-Updates von externen Web Service CLR gespeicherte Prozeduren und SQL-Aufträge verwenden.

Wir haben eine Anwendung, die einige der Daten, die sie verfolgt, mit externen Datenfeeds synchronisiert. Die Synchronisierung läuft wöchentlich für alles und On-Demand für einzelne Updates, so dass ich eine bestehende Webservice-API hatte, um darauf zuzugreifen. Die Dinge sind bereits von einem Windows-Dienst geplant, aber ich dachte, warum nicht in der Lage, sie wie unsere anderen SQL-Jobs planen?

Ich erstellte eine CLR-gespeicherte Prozedur, die auf die Webservice-API der Anwendung verweist. Dann fügte ich ein paar parms für @RecordID hinzu, um eine einzelne Synchronisierung zu unterstützen, und plante sie in SQL-Jobs für den Enterprise Manager.

Jetzt kann ich den Job verwenden, um dB-Synchronisationen auszuführen oder die Prozedur in anderen SQL-Prozeduren oder Triggern zu verwenden, um Daten vom externen Feed zu aktualisieren.

Es kann sauberer sein, die Anwendung webservice API in der Zukunft zu nehmen und nur den externen Webservice direkt zu verwenden. Für den Moment war dies jedoch sehr schnell zu implementieren und eine coole Möglichkeit, die Funktionalität auf die SQL-Gruppe zu erweitern.

1

Es ist sehr nützlich, um Daten aus einem System herauszuholen, das keine traditionelle SQL-Schnittstelle bietet, oder die Implementierung dieser Schnittstelle durch den Hersteller ist unterdurchschnittlich.

Wir haben eine Kernanwendung auf der alten MUMPS-Plattform, die auf der Intersystems Cache-Datenbank ausgeführt wird. Die Daten sind hierarchisch, nicht relationaler Natur. Das globale Hauptarray (d. H. Tabelle) weist mehrere Datenebenen und Elemente auf, die alle nach Kontonummern gruppiert sind. Wenn nur eine Spalte gescannt wird, muss die gesamte globale Datei von der Festplatte geladen werden, und es dauert mehr als 8 Stunden. Der Anbieter stellt einen ODBC-Treiber und Zuordnungen zu den Globals bereit, führt jedoch häufig zu Scans und extrem langsamen Abfragen.

Ich habe eine Tabellenwertfunktion erstellt, die ein ObjectScript-Programm (Intersystem-Dialekt von MUMPS) ausführt, es auf dem Cache-Server ausführt und die Ausgabezeilen als Datenzeilen zurückgibt. Ich kann den Datenzugriffspfad auf der MUMPS-Seite mikromanagen (das ist wirklich, was es braucht, um einen effizienten Datenzugriff zu erhalten), indem ich ein spezifisches Programm zur Ausführung auf dieser Seite anbiete und die Daten dann einfach in MSSQL als eine Ad-hoc-Inline-Datenquelle importiere.

Ich kann den TVF verwenden, um die Datenauswahl zu fahren, oder CROSS APPLY verwenden, um Nachschläge am anderen Ende zu machen, und es ist einigermaßen effizient. Ich kann sogar mehrere Abfragen am entfernten Ende parallel ausführen, wenn ich MSSQL dazu zwinge, einen parallelen Ausführungsplan zu verwenden.

+0

> "und gibt die Ausgabezeilen als Datenzeilen zurück." Haben Sie die Daten zuerst in eine System.Data.DataTable geschrieben? Ich habe einige Hilfsfunktionen, um Datentabellen zu schreiben, aber ich frage mich, wie es zum Beispiel mit einem IEnumerable gemacht werden könnte. – tbone

+0

Es gibt eine FillRow-Methode mit der Streaming Table Valued Function, die eine feste Projektion von Zeilen aufweist. In der ursprünglichen Version gab ich bis zu 8 Zeichen Felder aus der Abfrage als F1, F2, F3 ... –

+0

Danke - relevantes Beispiel denke ich: http://StackOverflow.com/Questions/6901811/sql-clr-streaming- Tabellenwert-Funktion-Ergebnisse – tbone

Verwandte Themen