Ubah standar lebar sistem untuk maxrecursion

12

Bagaimana cara mengubah nilai standar seluruh sistem MAXRECURSION?

Secara default 100, tapi saya perlu meningkatkannya menjadi sekitar 1000.

Saya tidak dapat menggunakan petunjuk permintaan karena saya menggunakan program yang mengambil permintaan saya dan menjalankannya untuk saya dan sayangnya saya tidak bisa mengatasi batasan ini.

Namun, saya memiliki hak admin pada instance server. Saya sudah mencari-cari di sisi server, tapi saya tidak melihat apa pun di sana yang terkait dengan opsi kueri atau rekursi. Saya berasumsi ada memiliki menjadi suatu tempat di mana saya bisa memperbarui seluruh sistem default.

Ada ide?

carl.anderson
sumber
3
Saya hanya ingin memeriksa Anda memahami batas 100 hanya pada tampilan dan fungsi dan bahwa Anda dapat menggunakan prosedur tersimpan dan menimpa secara lokal di sana? Apakah ada kebutuhan khusus untuk menggunakan fungsi? Karena rekursi cukup tidak efisien, saya juga menyarankan berjalan hierarki hanya sekali dan menyimpan output dalam sebuah tabel. Anda kemudian bisa membuat fungsi yang merujuk ke tabel itu. Bagaimana menurut anda?
wBob

Jawaban:

10

Jika kueri Anda memiliki bentuk umum, Anda mungkin dapat menambahkan petunjuk maxrecursion yang diperlukan menggunakan satu atau lebih panduan paket.

Mungkin ada cara untuk memperbaikinya. Jika Anda menambahkan detail kueri spesifik ke pertanyaan Anda, kami mungkin dapat menyelesaikannya untuk Anda. Biasanya, Anda akan melacak SQL yang benar-benar mengenai server, atau mendapatkan formulir parameter menggunakan prosedur built-in sys.sp_get_query_template , dan kemudian membuat panduan TEMPLATE dan / atau OBJECT / SQL plan.

Lihat dokumentasi untuk informasi lebih lanjut:

Panduan paket perlu divalidasi ulang setiap kali kode aplikasi berubah, dan ketika SQL Server ditambal atau ditingkatkan. Ini seharusnya hanya menjadi bagian dari siklus pengujian normal Anda.

Perhatikan bahwa validasi panduan paket menggunakan sys.fn_validate_plan_guide dapat melaporkan kesalahan secara tidak benar jika pernyataan yang dipandu merujuk tabel sementara. Lihat pertanyaan ini:

Validasi panduan paket dengan fn_validate_plan_guide memberikan hasil positif palsu

The Rencana Panduan Sukses dan Rencana Panduan Gagal Profiler dan Acara diperpanjang kelas juga dapat digunakan untuk memantau rencana aplikasi panduan.

Connect dihentikan sebelum saran peningkatan produk Izinkan nilai batas MAXRECURSION selain 100 untuk tampilan dan UDF oleh Steve Kass diimplementasikan. Jika Anda ingin mengambilnya dengan Microsoft sekarang, lihat opsi di SQL Server bantuan dan umpan balik .

Paul White 9
sumber
Ini membuat frustrasi dan tidak menjawab pertanyaan alih-alih mengubur kami di lubang kelinci dokumentasi. EF Core (ORM tipikal) menghasilkan pertanyaan untuk Anda bahkan jika Anda memberikannya pernyataan SQL mentah yang dibungkusnya dalam pemilihan induk, siapa pun yang menggunakan EF Core memiliki masalah ini. Solusi Anda adalah "rencanakan permintaan Anda".
War
@ Perang Ini jawaban terbaik yang bisa saya berikan untuk pertanyaan khusus ini dengan detail yang disediakan. Satu-satunya cara saya tahu untuk menambahkan petunjuk rekursi maksimum adalah melalui SQL Server yang disebut Panduan Rencana, yang tidak ada hubungannya dengan "perencanaan kueri Anda". Jika Anda memiliki pertanyaan spesifik, tanyakan secara terpisah dengan contoh minimal yang dapat direproduksi .
Paul White 9
9

Jika Anda benar-benar harus menggunakan fungsi (batasan alat ETL Anda seperti yang Anda maksudkan), Anda dapat menentukan OPTIONsebagai bagian dari fungsi bernilai tabel multi-pernyataan, misalnya sesuatu seperti ini:

CREATE FUNCTION dbo.udf_MyFunction ( @StartID INT ) 
RETURNS @tv TABLE
(
id INT
)
AS
BEGIN

    WITH Episodes( xlevel, PersonID, EventID, EpisodeID, StartDT, EndDT ) AS (
    -- Anchor case - the first EventID for each person.
    SELECT 1 AS xlevel, PersonID, EventID, @StartID, StartDT, EndDT 
    FROM dbo.EventTable
    WHERE EventID = @StartID

    UNION ALL

    SELECT xlevel + 1, et.PersonID, et.EventID, c.EventID + 1, et.StartDT, et.EndDT
    FROM Episodes c
        INNER JOIN dbo.EventTable et ON c.PersonID = et.PersonID
            AND et.EventID = c.EventID + 1
    --WHERE c.EventID <= (@StartID + 99)
    )
    INSERT INTO @tv
    SELECT PersonID
    FROM Episodes
    OPTION ( MAXRECURSION 1000 )

    RETURN

END
GO

Ini juga berfungsi untuk saya ketika dibungkus dalam tampilan seperti yang Anda sarankan alat ETL Anda. Tidak ada cara untuk mengubah seluruh sistem ini, tetapi karena rekursi dapat menjadi tidak efisien, ini mungkin merupakan hal yang baik. Anda tidak bisa menentukan petunjuk kueri (menggunakan OPTION) di dalam tubuh fungsi bernilai tabel inline, seperti dalam contoh Anda.

Pertimbangkan mengubah proses Anda untuk berjalan hierarki hanya sekali ketika Anda menerima Episode Anda dan menyimpan hasilnya dalam tabel relasional. Anda dapat menggunakan proc yang disimpan untuk melakukan ini sehingga tidak akan mengalami batasan ini.

Saya juga berpikir mungkin ada bug dalam kode Anda: jika CTE Anda bergabung di personId dan berulang di eventId, eventId 101 akan muncul dua kali saya pikir, sebagai duplikat. Mungkin saya salah mengartikan kode Anda, beri tahu saya pendapat Anda.

HTH

wBob
sumber
ini tidak berfungsi karena parameter "OPSI" harus diterapkan pada tingkat pernyataan dan pernyataan yang dimaksud adalah panggilan ke fungsi, ini akan mengembalikan pengecualian.
War
0

Saya mengambil inspirasi dari topik ini .

Inilah yang saya lakukan untuk menyelesaikan masalah.

CREATE FUNCTION MySchema.udf_MyFunction(@StartID INT) 
RETURNS TABLE 
AS RETURN
WITH
Episodes(PersonID, EventID, EpisodeID, StartDT, EndDT) AS (
  -- Anchor case - the first EventID for each person.
  SELECT PersonID, EventID, @StartID, StartDT, EndDT 
  FROM MySchema.EventTable
  WHERE EventID = @StartID
UNION ALL
  SELECT
    ...
  WHERE
    EventID <= (@StartID + 99)
)
SELECT * FROM Episodes

Lalu saya memanggil fungsi ini seperti ini:

WITH
Episodes AS (
  SELECT * FROM MySchema.udf_MyFunction(1)
UNION ALL
  SELECT * FROM MySchema.udf_MyFunction(101)
UNION ALL
  SELECT * FROM MySchema.udf_MyFunction(201)
-- ...
UNION ALL
  SELECT * FROM MySchema.udf_MyFunction(901)
)
SELECT * FROM Episodes

Dengan cara ini, tidak ada logika CTE saya harus diulang dan saya tidak membayar apa pun tambahan dalam hal kinerja. Ini adalah gangguan yang harus dilakukan dengan cara ini, tetapi saya bisa hidup dengannya.

carl.anderson
sumber
3
Saya tidak melihat bagaimana ini memecahkan masalah rekursi. Doa fungsi tidak rekursif.
ypercubeᵀᴹ
@ ypercubeᵀᴹ - bit rekursif dari CTE pergi ke tempat saya memiliki ellipsis - logika rekursif khusus saya tidak benar-benar relevan dengan masalah, tetapi Anda dapat mengasumsikan bahwa CTE sebenarnya adalah rekursif. The whereklausul setelah elipsis mencegah terlalu banyak recursions terjadi dengan menggunakan parameter fungsi sebagai kendala. Saya kira harus ada pernyataan setelah definisi CTE. Saya akan menambahkannya.
carl.anderson
3
Saya mengerti betul bahwa CTE bersifat rekursif. Masalahnya adalah bahwa doa (panggilan fungsi) tidak rekursif . Misalnya, Anda memanggil fungsi dengan titik awal (baris) dengan EventID=1(dan 101.201, ... 901). Tetapi kueri asli (jika dijalankan dengan MAXRECURSION = 100000000) mungkin tidak pernah mengunjungi baris dengan EventID=101(dan 201, .., 901). Jadi dua pertanyaan (asli dan solusi Anda) dapat memberikan hasil yang berbeda (tidak ada baris dengan 101 di yang pertama, ya di ke-2)! Atau mungkin mengunjungi 101 tetapi sebelum langkah 100, jadi solusi Anda akan menyertakan baris dua kali dalam hasil (lagi berbeda)
ypercubeᵀᴹ
2
Kecuali tentu saja data terhubung melalui nilai EventID berurutan (1,2,, 3 ..., 99.100.101, ..). Dalam hal ini, Anda tidak perlu CTE rekursif sama sekali.
ypercubeᵀᴹ
Bagaimana cara mengatasi masalah kedalaman yang tidak diketahui untuk sesuatu seperti ... mendapatkan pohon dari jalur DMS yang diberikan sebagai rowset?
War