Oibríonn DBMS maidir leis seo ar na prionsabail chéanna - "Dúirt siad liom tochailt, mar sin déanaim tochailtNí hamháin gur féidir le d’iarratas próisis chomharsanachta a mhoilliú, agus acmhainní próiseálaí á n-úsáid i gcónaí, ach freisin “titim” ar an mbunachar sonraí iomlán, “ag ithe” gach cuimhne atá ar fáil. cosaint i gcoinne atarlú gan teorainn - freagracht an fhorbróra féin.
In PostgreSQL, tá an cumas chun fiosrúcháin athfhillteacha a úsáid trí WITH RECURSIVE
Ná scríobh ceisteanna athfhillteacha
Agus scríobh cinn neamh-athfhillteach. Le meas, Do K.O.
Go deimhin, soláthraíonn PostgreSQL go leor feidhmiúlacht ar féidir leat a úsáid chun aon athfhillteach a chur i bhfeidhm.
Bain úsáid as cur chuige bunúsach difriúil i leith na faidhbe
Uaireanta is féidir leat breathnú ar an bhfadhb ón "taobh difriúil". Thug mé sampla de chás den sórt sin san alt
WITH RECURSIVE src AS (
SELECT '{2,3,5,7,11,13,17,19}'::integer[] arr
)
, T(i, val) AS (
SELECT
1::bigint
, 1
UNION ALL
SELECT
i + 1
, val * arr[i]
FROM
T
, src
WHERE
i <= array_length(arr, 1)
)
SELECT
val
FROM
T
ORDER BY -- отбор финального результата
i DESC
LIMIT 1;
Is féidir rogha ó shaineolaithe matamaitice a chur in ionad an iarratais seo:
WITH src AS (
SELECT unnest('{2,3,5,7,11,13,17,19}'::integer[]) prime
)
SELECT
exp(sum(ln(prime)))::integer val
FROM
src;
Úsáid Generation_series in ionad lúba
Ligean le rá go bhfuil muid ag tabhairt aghaidhe ar an tasc a ghiniúint gach réimír féideartha do teaghrán 'abcdefgh'
:
WITH RECURSIVE T AS (
SELECT 'abcdefgh' str
UNION ALL
SELECT
substr(str, 1, length(str) - 1)
FROM
T
WHERE
length(str) > 1
)
TABLE T;
An bhfuil tú cinnte go bhfuil gá agat le hathchúrsaí anseo?.. Má úsáideann tú LATERAL
и generate_series
, mar sin ní bheidh CTE uait fiú:
SELECT
substr(str, 1, ln) str
FROM
(VALUES('abcdefgh')) T(str)
, LATERAL(
SELECT generate_series(length(str), 1, -1) ln
) X;
Athraigh struchtúr an bhunachair shonraí
Mar shampla, tá tábla teachtaireachtaí fóraim agat le naisc ón té a d’fhreagair, nó snáithe isteach
CREATE TABLE message(
message_id
uuid
PRIMARY KEY
, reply_to
uuid
REFERENCES message
, body
text
);
CREATE INDEX ON message(reply_to);
Bhuel, is cosúil le hiarratas tipiciúil chun gach teachtaireacht ar ábhar amháin a íoslódáil:
WITH RECURSIVE T AS (
SELECT
*
FROM
message
WHERE
message_id = $1
UNION ALL
SELECT
m.*
FROM
T
JOIN
message m
ON m.reply_to = T.message_id
)
TABLE T;
Ach ós rud é go dteastaíonn an t-ábhar iomlán uainn i gcónaí ón bhfréamhtheachtaireacht, cén fáth nach ndéanaimid cuir a ID le gach iontráil uathoibríoch?
-- добавим поле с общим идентификатором темы и индекс на него
ALTER TABLE message
ADD COLUMN theme_id uuid;
CREATE INDEX ON message(theme_id);
-- инициализируем идентификатор темы в триггере при вставке
CREATE OR REPLACE FUNCTION ins() RETURNS TRIGGER AS $$
BEGIN
NEW.theme_id = CASE
WHEN NEW.reply_to IS NULL THEN NEW.message_id -- берем из стартового события
ELSE ( -- или из сообщения, на которое отвечаем
SELECT
theme_id
FROM
message
WHERE
message_id = NEW.reply_to
)
END;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER ins BEFORE INSERT
ON message
FOR EACH ROW
EXECUTE PROCEDURE ins();
Anois is féidir ár bhfiosrúchán athfhillteach iomlán a laghdú go dtí seo:
SELECT
*
FROM
message
WHERE
theme_id = $1;
Úsáid "teorainneacha" i bhfeidhm
Mura bhfuilimid in ann struchtúr an bhunachair sonraí a athrú ar chúis éigin, féachaimis cad is féidir linn a bheith ag brath air ionas nach n-eascróidh earráidí gan deireadh fiú má bhíonn earráid sna sonraí.
Cuntar doimhneacht athfhillteach
Níl le déanamh againn ach an cuntar a mhéadú faoi cheann amháin ag gach céim athchúrsála go dtí go sroichimid teorainn a mheasaimid ar léir a bheith neamhleor:
WITH RECURSIVE T AS (
SELECT
0 i
...
UNION ALL
SELECT
i + 1
...
WHERE
T.i < 64 -- предел
)
Pro: Nuair a dhéanaimid iarracht lúb a dhéanamh, ní dhéanfaimid níos mó ná teorainn sonraithe na n-atriallta “go domhain”.
CONS: Níl aon ráthaíocht ann nach ndéanfaimid an taifead céanna a phróiseáil arís - mar shampla, ag doimhneacht 15 agus 25, agus ansin gach +10. Agus níor gheall aon duine faic faoi “leithead”.
Go foirmiúil, ní bheidh a leithéid de atarlú gan teorainn, ach má thagann méadú easpónantúil ar líon na dtaifead ag gach céim, tá a fhios againn go léir go maith conas a chríochnaíonn sé...
Caomhnóir an "chosán"
Mar a chéile cuirimid na haitheantóirí oibiachta ar fad ar tháinig muid trasna orthu feadh an chosáin athchúrsála isteach in eagar, ar “conair” uathúil é:
WITH RECURSIVE T AS (
SELECT
ARRAY[id] path
...
UNION ALL
SELECT
path || id
...
WHERE
id <> ALL(T.path) -- не совпадает ни с одним из
)
Pro: Má tá timthriall sna sonraí, ní dhéanfaimid an taifead céanna a phróiseáil arís agus arís eile laistigh den chosán céanna.
CONS: Ach ag an am céanna, is féidir linn na taifid go léir a sheachbhóthar go litriúil gan muid féin a athrá.
Teorainn Fad Conair
Chun staid an athchúlaithe a sheachaint “ag fánaíocht” ag doimhneacht dothuigthe, is féidir linn an dá mhodh roimhe seo a chur le chéile. Nó, mura dteastaíonn uainn tacaíocht a thabhairt do réimsí nach bhfuil gá leo, cuir meastachán ar fhad an chosáin leis an gcoinníoll chun leanúint ar aghaidh leis an athchúrsa:
WITH RECURSIVE T AS (
SELECT
ARRAY[id] path
...
UNION ALL
SELECT
path || id
...
WHERE
id <> ALL(T.path) AND
array_length(T.path, 1) < 10
)
Roghnaigh modh a thaitníonn leat!
Foinse: will.com