á ááá á ááŞáą á¨ááá á áşáá˝ á¨ááá አá¨á˝áŤá á˘áŽáá˝ á áľá°áłáłáŞáá˝ á°áááá áá
áľááá
ᣠáĽáá°áá á áŁá á¨á°áŤá á¨ááἠááłáá˝ á á ááą áá âá¨áŁáľâ áĽáŤááá˝á áááááŤá˝á á¨ááŤáľá°áá
á áá°áá - á¨áŤáłá˝áá˘
á¨áá á á áá á°á¨á᪠ááá፠á ááľ á áľá°áłá˝ ááłá á áłááˇá á ááááŞáŤ áááťá¸áľ áĽá á¨ááŤá á¨á áááá ááľááľ á á°á¨áłáłá ááťáťáŤ áĽáŤá á á ááŤáł áĄáľáá˝ áŁáĽáŤááłááłá¸á á áĽáŠ ááááá˝ áĽáť á¨á°áŠáľá˘
0: á°á ááá áá ááá?
[KDPV
á ááľ á°á áá á áľá áľá "ááŁá" ááá á˛ááá áĽááá áá áá áááľ áá? áĽáá° áááľ ááĽá¨ááá âáááâ ááá á ááŤá˝ á ááááĽáᢠ... LIKE '%ŃОСа%'
- ááááŤáąá á¨ááŤá áá¤áą áĽáť áłááá áŤáŤáľáłá 'РОСаНиŃ'
и 'ĐагаСин РОСа'
áá 'ĐŃОСа'
áĽá áĽáá˛áŤáá 'ĐОП Đода ĐĐžŃОСа'
.
á°á ááá ááĽáą áĽáá°ááŤáááĄáľ á áááľ á°áááľ á°á¨á áá ááááłá á áá ááááŞáŤ áááá á áááą ááľáĽ áĽá á¨á áá á°ááá
áŤáľáááľ á áá ááááŤá ááĽáˇá ᢠá áá°á áłá°áááá
áá˛áŤáá áááľ ááťáá - áá˘áá°áááá áá¤áľá˘
1: áľáŤáá áááľáĄ
áĽá á¨áá
á á á áá , á ááľ á°á á á°áᨠáááł á áááŁá 'ŃОС ПагаС'
, áľááá
áĽáŤááłááąá áá á á
áľá-á
áĽáŤ áááá á ááĽááľ. á áᣠá ááľ á°á áá á¨áá°ááá áá áá áĽá âáááá˝â á¨áááľ ááá
ááá¨á¨áťá áá ááŁá ááá ááľá áľ á áŁá ááá áá - ááááá á¨ááá áá°á áá
áá áĽáá´áľ áĽáá°ááá áááá¨áąá˘
á á á ááá áĄáĄ áá áá˝áአááľáááśá˝á áááááľ á¨ááá˝ á áá áááľá áá. á ááłááľ áá á¨ááłá áľááłáá á áĽááá áá áá
á¨á áĽáľáľáŤááľ ááᢠáá áŤá°ááá?
1.0: ááŤá á¨ááá áá°á
áŚá ᣠááá á¨áŁáľ áá ᣠááá ááľá¨á á ááááá - áá˛ááľ áĽááľá á! á¨áá¨á ááą áá á¨áá á¨ááá áá°á áĽáá˛áŤá°áአááááąáá¸áᥠSphinxᣠElasticSearcháŁ...
á¨áľáŤ á ááŤáᣠááá áĽááłá á¨áááłá°á áĽá á¨áááŚá˝ ááĽááľ á ááá ááá áľ á¨áá áá
ᢠáá á áĽá áááł á áá°áá ᣠááááŤáąá áááá ááĽáŤááłááą á°áá á á¨áá¨áááá á áĽáą áá፠ááἠáááá ááľáĽ áĽáť ááᢠáĽá ááᥠá áľááá á¨áá°á á°ááááááľ á áá - áĽá á áľá°áłáłáŞá á áá áŤááąá á¨áᣠ'ĐагаСин РОСа'
, á¨á፠á¨5-10 á°á¨ááľ á áá á˘áááá áĽá፠ááááá¨áľ áĽáá°á¨áłá áĽá ááá ááááľ áĽá áá¨á áĽáá°áááá á áľááľá áŤáľáłááłá.
áľááá - áĽááľáá á ááĽáł "á áá¨á ááą ááľáĽ" áááá. áĽáá° áĽáľá áá, PostgreSQL áá áá áĽááľáá°áá ááá áľááá, áĽá á ááľ á ááŤá áĽáť á áá°áá - áĽá áĽáááá¨áłá¸ááá.
1.1ᥠâáłááâ áááľ ááĽá¨ááá
"áááľ ááĽá¨ááá" á¨áááá áá áĽááááá. áá ááá¨á á áá ááá á áááľ ááĽá¨ááá (áĽá á áá°á á ááááŤáá˝ áĽááłá!) á áŁá áĽáŠ ááá á áá˘
áá´áá ááááá á¨áá¨á°ááá áłá á áááá°áľ áĽáááááĄ-
CREATE TABLE firms(
id
serial
PRIMARY KEY
, name
text
);
áĽá áĽá፠7.8 áááŽá á¨áĽááá°á áľáá áśá˝á ááááŚá˝á áĽáá°á áá¸ááá áĽá áĽáá ááá¸ááááĄ
CREATE EXTENSION pg_trgm;
CREATE INDEX ON firms USING gin(lower(name) gin_trgm_ops);
áááá ááľáá ááá á¨ááááŞáŤáášá 10 ááááŚá˝á áĽáááááĄ-
SELECT
*
FROM
firms
WHERE
lower(name) ~ ('(^|s)' || 'ŃОСа')
ORDER BY
lower(name) ~ ('^' || 'ŃОСа') DESC -- ŃнаŃаНа "наŃинаŃŃиоŃŃ Đ˝Đ°"
, lower(name) -- ĐžŃŃĐ°ĐťŃнОо пО Đ°ĐťŃавиŃŃ
LIMIT 10;
áĽááá˛á áŤ... 26msᣠ31MB ááἠá ááĽáĽ áĽá ᨠ1.7K á áá á¨á°áŁáŠ ááááŚá˝ - á 10 ááááá˝. á¨áľáá ááŞáá˝ á áŁá áĽá áá¸á ᣠá¨á áá áááŁá ááá á¨áá?
1.2ᥠá á˝áá áááá? FTS áá!
á áĽáááĽ, PostgreSQL á áŁá áááá áŤáááŁá
CREATE INDEX ON firms USING gin(to_tsvector('simple'::regconfig, lower(name)));
SELECT
*
FROM
firms
WHERE
to_tsvector('simple'::regconfig, lower(name)) @@ to_tsquery('simple', 'ŃОСа:*')
ORDER BY
lower(name) ~ ('^' || 'ŃОСа') DESC
, lower(name)
LIMIT 10;
áĽáá á¨áĽáŤá á áááá áľááŠááľ áľáá˝ á¨áľáśááᣠá°ááąá á ááá˝ ááጠ11 áá´. áĽá 1.5 áĽáĽá áŤáá° ááá ἠáá á¨áĽá - á á á ááá 20MB. áá áĽáá ᣠáľáὠᣠá¨á°áťáá ᣠááááŤáąá á¨áááá á áľáá áá á ᣠáá¸á፠á¨ááááľ áĽáľá á¨á áŤá áá ᣠáĽá áĽáŤááłááą á°á¨á᪠á¨ááἠáá˝ á¨á˛áľá á¨ááá á á ááĽáŤáá âáĽáŹááľâ ááá˘
1.3: á ááá áááłá?
á¨áá°áá áĽáŤá áááá á°á áĽáŠ áá, ááá áá á áá ááś áşá áá á¨áá°á° áĽáť áááŁá 2TB ááἠááá áĽ. á áĽáŠ áááł, á¨ááľáłááť, áá áĽáľááá˝ áŤááá, á¨á፠á¨á˛áľá. áľááá áľáá˝ áááľá¨á áĽáááá.
á°á ááá áá¨áľ á¨áááááá áĽááľáłááľ á ááááŞáŤ "á áááá...". áľááá
áá
á áášá
ááá áá text_pattern_ops
! áĽá á¨áááááá¸á áĽáľá¨ 10 á¨áá°ááą ááááŚá˝á âá áâ á¨ááá áĽáť á¨FTS áááá á°á á
áá á ááĽá á áá¨á¨áľ á ááĽáá˘
CREATE INDEX ON firms(lower(name) text_pattern_ops);
SELECT
*
FROM
firms
WHERE
lower(name) LIKE ('ŃОСа' || '%')
LIMIT 10;
áĽá á á áŁá áĽáŠ á ááťá¸á - á á áá 0.05ms áĽá á¨100 áŞáŁ áľáá˝ á áá á ááĽáĽ! áĽáť á¨á¨áłáá á áľá áá°áá°áá°á ááá á áá¤áą ááľáĽ áĽááłáá á:
SELECT
*
FROM
firms
WHERE
lower(name) LIKE ('ŃОСа' || '%')
ORDER BY
lower(name)
LIMIT 10;
áŚá ᣠá¨áá ááá á¨á áá á áá áŤá áŤá á ááá á áá°áá - á˘áá´ááľ áŤá áááľáá ᣠáá áá°áŁá á ááá⌠áĽáą á áĽááἠᣠá¨ááłáá á ááŤá áĽá áĽáĽá á¨á áá áá¤áłá áá ᣠááâŚ
1.4ᥠâá ááá á¨ááľâ
áá á ááá ááááá áĽá á ááá á áá°á áááľ áá°áá°áá ááá áá á¨ááŤáľá˝á á˘áá´ááľ á á - áá°á á btree!
CREATE INDEX ON firms(lower(name));
á¨áĽáŤáá áĽáŤá áĽáť âá áĽá áá°áĽá°áĽâ á áá áľáĄ-
SELECT
*
FROM
firms
WHERE
lower(name) >= 'ŃОСа' AND
lower(name) <= ('ŃОСа' || chr(65535)) -- Đ´ĐťŃ UTF8, Đ´ĐťŃ ĐžĐ´Đ˝ĐžĐąĐ°ĐšŃОвŃŃ
- chr(255)
ORDER BY
lower(name)
LIMIT 10;
á áŁá áĽáŠ - áá°áŁá áá°áŤá ᣠáĽá á¨ááĽá¨áľ áááł âá áá ááá˝áâ áá áááŤá ᣠᨠâáášá â FTS á áşáá˝ á¨ááá አáá á¨á áá áá¤áłá! á¨ááá¨á á á ááľ áĽáŤá ááľáĽ á ááľ áá ááľááἠáĽáť áááĄ-
(
SELECT
*
FROM
firms
WHERE
lower(name) >= 'ŃОСа' AND
lower(name) <= ('ŃОСа' || chr(65535)) -- Đ´ĐťŃ UTF8, Đ´ĐťŃ ĐžĐ´Đ˝ĐžĐąĐ°ĐšŃОвŃŃ
кОдиŃОвОк - chr(255)
ORDER BY
lower(name)
LIMIT 10
)
UNION ALL
(
SELECT
*
FROM
firms
WHERE
to_tsvector('simple'::regconfig, lower(name)) @@ to_tsquery('simple', 'ŃОСа:*') AND
lower(name) NOT LIKE ('ŃОСа' || '%') -- "наŃинаŃŃиоŃŃ Đ˝Đ°" ĐźŃ ŃМо наŃНи вŃŃĐľ
ORDER BY
lower(name) ~ ('^' || 'ŃОСа') DESC -- иŃпОНŃСŃоП ŃŃ ĐśĐľ ŃĐžŃŃиŃОвкŃ, ŃŃĐžĐąŃ ĐРпОКŃи пО btree-индокŃŃ
, lower(name)
LIMIT 10
)
LIMIT 10;
ááá°áá áááľ áá áá
ááá¸áá áἠáá á á¨ááááŞáŤá á¨á°á á áá áŤáá° á¨á°ááá° áĽáť áá á¨áá¨á¨áťá LIMIT
á¨ááľááŽá˝ áĽááľ. áľááá
á¨áá áá
ááťáťáŤ áá´ áĽá¨á°áááአááá˘
áľááá á áᣠá áá áááąá btree áĽá áá á á á¨á´áá áá á áá ᣠáá á áľáłá˛áľá˛ááľ áá°á¨áľ ፠á°ááá ᢠᨠ10% áŤááą áĽáŤááá˝ á¨ááá°áá áĽááł á áááá áá á°áá°áá. áááľáᣠááĽáŤá á áľááľá á ááłáá áĽáá°áá áŤá áááá°á áá°áŚá˝áŁ á á ááá á¨á áááá ááĽáśá˝á áááł áá° á ááľ áşá áá áŤá á ááááľ á˝ááá!
1.5*: áŤá ááá ááľá¨á áĽáá˝ááá
á¨á áŤá LIKE
á¨á°áłáłá° áá°áá°á áĽááłáá áá á°á¨áááááᢠááá áá ᨠUSING áŚááŹá°áá á ááĽááľ "á áľááááá ááááľ áá" áá°á¨á áá˝áá.
á ááŁáŞááľ ááááłá
ASC
. á á°á¨ááŞáᣠá á ááľ á ááá ááľáĽ á¨á ááľ á¨á°áá°á á áááľ áŚááŹá°á áľá áááá˝ áá˝ááá˘USING
. á¨ááááľ áŚááŹá°á á¨á ááłááľ á¨á˘-áá áŚááŹá°áŽá˝ á¤á°á°áĽ áŤáá° ááá á¨á áá á áŁá ááá á áá áľá˘ASC
á áĽáááá áá á°ááŁáŁáUSING <
иDESC
á áĽáááá áá á°ááŁáŁáUSING >
.
á áĽá áááł, "áŤáá°" áá ~<~
:
SELECT
*
FROM
firms
WHERE
lower(name) LIKE ('ŃОСа' || '%')
ORDER BY
lower(name) USING ~<~
LIMIT 10;
2: áĽáŤááá˝ áĽáá´áľ áááá áááá
á áá ááľáľáľáľ áá ááá áá ááľ áááľ áŤá á âááá ááľâ áĽáŤááŤá˝áá áĽáá°áááá áĽá âá¨ááâ á á ááá á¨áááľ á°áááľ á¨ááľáłááľ á˝ááłá á ááŤáłáŠ á áááá˝ áĽáá°áá áľáááá á áľáááááá˘áááááŤáá˝ á¨á°áአááł) á 5.5TB - áááľá á¨ááááŞáŤáá á¨á áá á˘
á á ᣠá áĽááἠᣠá¨áĽá áááľ á áľáá áĽá á¨áĽáŤ áŤá á¨ááŻá ᣠáá á á°ááłáłá áá á á áá°áá! áá áááľ áĽáá á¨áá ááá á áł áá - áĽáľá˛ áĽááá á áľá˘
2.1ᥠá¨áá˝áł ááááľ
á á ááľ áá áľáŁ áá á¨áĽáľááľ áĄáľá á¨á°ááłáłáŠáŁ ááá áá á¨á°á áá¤áľ áŤáá ááŁá á¨á°áá áááľ áááᣠááá áá° áááᥠ"ááááá" áááľá¨á áááᢠáŤá áá˝ áłá°áł áááἠáááľá áá? áĽáá˝á¨á¨á¨áá áľ!
( ... LIMIT <N> + 10)
UNION ALL
( ... LIMIT <N> + 10)
LIMIT 10 OFFSET <N>;
á áá áááá˘á ááá ááááľ áłááá á "áá˝-áá˝" á ááŤá á¨ááá áá¤áśá˝á áááἠááłá¨áľ á°á˝áá.
á áĽáááĽ, á áĽáááą, ááĽáŤááłááą ááŁá á¨áá¨á áá˝ áĽá áĽá áĽá ááá áŁá (ááá á¨áá°áá áá ᣠââáĽá á¨áááĽáá ᣠáĽá á áľááááá âá áŤáľâ) - áááľá ᣠáá ááá˝ áá¨-ááľá ááᢠááá áá ááááá á áááĽáá á°á°áááááľ á á ááááš ááľáĽ á¨á°á¨áá¸á áááᣠáá áľáá፠áá áá áááá á¨á áá áľááá ááááá˘
2.2ᥠáĽáááł á¨áá ááá áĽááááá
á á ááľ áá áľ ááá˘á ááá á¨á°áááá ááá á ááἠááŁááľá˘ áŤááá áĽáŤá á áá áá° CTE á¨á°áá¨á áľ á¨áá á°áá á¨áĽáĄ-
WITH q AS (
...
LIMIT <N> + 10
)
SELECT
*
, (SELECT ...) sub_query -- какОК-ŃĐž СапŃĐžŃ Đş ŃвŃСаннОК ŃайНиŃĐľ
FROM
q
LIMIT 10 OFFSET <N>;
áĽá áĽáá°ááŤá áá ᣠáááľ áá áá á 10 á¨á°áááą ááááŚá˝ áĽáť áľáááááá ᣠáŤááá ᣠááĽá á áá°áá ...
2.3ᥠááŠááľ áľááá á¨áá˝ áĽá ááá¨áľ á¨áá˝ ááá˘
ᨠ2 á áááľ áá áá
á áĽáá°áá
ááááľ á¨áááá° ááἠáá°áľ ááľáĽ á¨áá áŚáł á á NOT LIKE
á ááá˝. á¨áá
á áá ááá ááá˝ ááᢠUNION ALL
ááááľ ááᨠá ááłááľ áá¤áśá˝ áááľ áá - á ááááŞáŤ á ááľáአááááŞáŤ áá áĽá á¨ááŤá áĽáá°áá - á áá
ááľáá á¨ááááŞáŤ áá ááááŞáŤ áá á°áááˇá. á áá°áĄ ááľáĽáŁ ááá ᨠ2 áá áááľ áá áá
ááááŚá˝ á¨ááááŞáŤá ááááŚá˝ áá ááááą áá˝ááá˘
ááᢠááááŤáąá á¨áááá ááá áá áá°áŤá?... ááá áĽáŤá á¨áá!
- áá áá á áĽáĽá á¨ááááŞáŤ ááááá˝
- DISTINCT á°ááĽáá¨áĽáŤááłááą ááľáá áá á ááłááá˝á áááááľ
WITH q AS (
( ... LIMIT <2 * N> + 10)
UNION ALL
( ... LIMIT <2 * N> + 10)
LIMIT <2 * N> + 10
)
SELECT DISTINCT
*
, (SELECT ...) sub_query
FROM
q
LIMIT 10 OFFSET <N>;
áŤá áááľ áá¤áą ᣠá áá¨á¨áť ᣠá áľááá á ááľ á áááľ áááá ááá áá ᣠáá áá° 2 á CTE áááľ áá áá âá¨ááĽá¨áâ áĽáľá á áŁá á¨á áŤá áá ᣠáĽá áŤááá ᣠá ááá˝ á¨á áá ááá ἠá¨áá˝á.
áá áá
á áŁá á¨ááŤáłááá ááá á áá°áá. ááá˘á áĽáá˛ááἠáľáá á¨á DISTINCT
áá°áá°ááľ áłááá áááá ááľáŽá˝ á á ááľ áá ááááŚá˝ ᣠá¨á፠á¨áááľ_áá áá ááľá - á¨áááľ áá áá áá¤áľ - áá˛áŤáá áĽá፠ááľáĽ á°áŤáˇáᢠá ááᣠáááľáá¸á DISTINCT
, á¨ááἠááłá ááľááá ááá¸á áá á¨á áľ 10 áááľ áá ááá˝ á áá°ááᣠáá ááá <2 * N> + 10!
2.4ᥠáľáĽáĽá á¨ááá á áá!
áľááá ᣠááá˘ááš áá¨áá - á áá°á¨ááá ᣠááááŤáąá á°á ááá á ááá˝ ááááĄá áá° ááá N áĽá´áśá˝ âáááľá°áŤá¨áâ á á áľáááľáľ áľáááá á¨á áĽáŤááłááąá ááŁá âáá˝â á ááá á áĽá á¨á°á°á° áááá¨áľá˘
á¨áá ááá á¨áᥠááá˘áá˝ áá° áĽáááą áĽáľáŞáᥠáĽá áĽáá°áá á áááľ ááš áá´á ááá áá áĽáľáŞááá áľá¨áľ áá°á°ááá ááá - áááľá á¨á ááłááľ ááááá˝ á ááľ ááŤá áĽáááľáłáá, á°á¨á᪠áááłáá˝á á ááŁáŤáľ, áá¤áąá ááłá, á¨ááŤá á¨áááĽááá ááŤá (á áĽá áááł N á áá¨áá áá), áĽá á፠áášá áĽáľáááá áľá¨áľ.
á á á ááá, á á°áŤáá ááá ááľáĽ N áá° 17 áşá á¨áá á áĽá´áśá˝ áá á°ááˇáᣠáĽá á á ááľ áá ááľáĽ á˘áŤááľ 4 áŞ.á áĽáá°áá áŤá áĽáŤááá˝ "á á°áá°ááą" á°áá áááᢠá¨áá¨á¨áťááš á áľáá¨áľ á°áá á á ááľ áľáááá˝ 1 áᢠáá á°á¨ áľááľáł...
Ô¸ŐÔ´ŐÔąŐŐŐŐ ÔłÔťŐ
ááá: hab.com