SQLSTATE[IMSSP]: Tried to bind parameter number 2101

H0w4rd
Člen | 99
+
0
-

Narazili jsme na nepříjemné omezení MSSQL:

SQLSTATE[IMSSP]: Tried to bind parameter number 2101. SQL Server supports a maximum of 2100 parameters

Nemáme tam žádné šílené prasárny, ani velká množství dat, pouze tisíce a někde desetitisíce. Stačí jenom, když má záznam hodně vazeb a ještě nad některými iteruju, nette db sestaví dotaz, kde je id IN (…) a tam klidně 3000 idček.

Není nějaká možnost, že by to v budoucnu řešila Nette database sama a odstínila programátora od tohoto nepříjemného omezení?

Musíme teď leccos přepisovat a nepoužívat ref ani related. Je to fakt časovaná bomba, protože se to začne objevovat na různých místech, jak budou přibývat data.

Používá vůbec někdo Nette database spolu s MSSQL?

Co s tím? Jak jste to řešili?

Editoval H0w4rd (3. 2. 11:31)

Kamil Valenta
Člen | 844
+
0
-

Ono to až tak nesouvisí přímo s MSSQL. Limit na počet bindovaných parametrů má patrně každé RDBMS. Ale je pravda, že málokdo má limit tak nízko, jako MSSQL. MySQL v pětkových verzích ho mělo jako uint16, MariaDB jako uint32. Aktuální verze z hlavy nevím, ale považoval bych ho za „nedosažitelný“.

Je pravda, že tohle mne na ref, related vždy dost děsilo a nikdy se to u nás moc nechytilo. Skutečnost, že selectiona od programátora z app vrstvy odchází v ne zcela predikovatelném stavu a až kodér v šabloně jí dá konečnou podobu, je riziková. Čekal bych, že takový dotaz bude i značně pomalý. Např. MySQL takové dotazy parsuje neuvěřitelně pomalu. Když někde očekáváme, že v IN() bude velký výčet, řešíme to tak, že si subdotaz, který ta ID získává, připravíme jako SQL literal a ten předhodíme vnějšímu dotazu. Rychlost je diametrálně jinde a zcela odpadne potřeba bindovat celou množinu jako samostatné parametry.

Kcko
Člen | 473
+
0
-

Kamil Valenta napsal(a):

Když někde očekáváme, že v IN() bude velký výčet, řešíme to tak, že si subdotaz, který ta ID získává, připravíme jako SQL literal a ten předhodíme vnějšímu dotazu. Rychlost je diametrálně jinde a zcela odpadne potřeba bindovat celou množinu jako samostatné parametry.

Ukázka prosím?

Nebo jak zrychlíš

<?php
SELECT * FROM tabulka WHERE id IN (1,2,3, ....n); --  klidně stovky / tisíce hodnot

?>

Editoval Kcko (4. 2. 13:33)

Kamil Valenta
Člen | 844
+
+2
-

Kcko napsal(a):

Nebo jak zrychlíš

<?php
SELECT * FROM tabulka WHERE id IN (1,2,3, ....n); --  klidně stovky / tisíce hodnot
?>

Pokud to nebyl jen bug v nějaké verzi MySQL, tak právě tohle:

<?php
SELECT * FROM tabulka WHERE other_id IN (1,2,3, ....n);
?>

pro stovky hodnot bylo hodně pomalé, ale

<?php
SELECT * FROM tabulka WHERE other_id IN (SELECT other.id FROM other);
?>

bylo několikanásobně rychlejší, ačkoliv množina ID byla totožná.

Kcko
Člen | 473
+
0
-

To jo, ale toto

<?php
SELECT * FROM tabulka WHERE other_id IN (1,2,3, ....n);
?>

se Ti většinou složí samo (když používáš related nebo ref), tak na konci dotazu Ti to Nette samo složí do této podoby kvůli optimalizaci, aby neposílal do DB tolik dotazů kolik je řádků.

Takže jestli si to předpřipravíš sám, že si posbíráš do stacku Id-čka a pak je ručně použiješ tak OK, ale to se mi moc nelíbí.

Jinak mimo téma, já třeba pracuju hlavně s MySQL 8 / Maria DB (odchylky mezi nimi nějaké minoritní jsou).
A tam je problém, když je hodně dat, tak i trapné sumarizační dotazy bez složitých WHERE podmínek či JOIN-ů jsou pomalé.

Editoval Kcko (4. 2. 14:18)

Martin Dřímal
Člen | 30
+
0
-

Kcko napsal(a):
Takže jestli si to předpřipravíš sám, že si posbíráš do stacku Id-čka a pak je ručně použiješ tak OK, ale to se mi moc nelíbí.

mssql vůbec neznám, dával jsem to ze zvědavosti ráno do perplexity a odkázalo mě to na stejné řešení. Buď dotaz složit do finálního stringu sám, jelikož to omezení by se mělo týkat jen nějakého sestavování prepared dotazů, nebo použít dočasnou tabulku/view s memory storage. První varianta je asi nesmysl, ale to s dočasnou tabulkou a subselectem by mohlo být snadno realizovatelné..
// kecám, s tím ->rel a ->ref to tak snadné nebude..

Editoval Martin Dřímal (4. 2. 14:23)

Kamil Valenta
Člen | 844
+
0
-

Ale vždyť o tom toto vlákno je, že ref/related to poskládá výčtem, což někdy nemusí být výhodné. O posílání n dotazů pro n řádků tady vůbec řeč není. Někdy je lepší to vyřešit už v modelu subdotazem. Osobní sympatie jsou bez další informace docela irelevantní.

David Grudl
Nette Core | 8282
+
+2
-

Tohle bych nejraději vyřešil nějak systémově, ale vůbec nevím jak. Tak jsem aspoň udělal commit, že číselné hodnoty v IN se nepředávají jako parametry, ale přímo v SQL.

H0w4rd
Člen | 99
+
0
-

To je úžasné, vydáš to prosím? Takhle jsme to řešili také. Nebo jsme problematická místa upravili, aby tam nebyl ref ani related. Jenže tenhle problém je časovaná bomba, jak budou růst data v databázi, časem se to objeví na různých dalších místech.

Editoval H0w4rd (5. 2. 9:59)

H0w4rd
Člen | 99
+
0
-

Vidím, že už to tam je ve verzi 3.2.7, děkuji.