{"id":472969,"date":"2025-09-02T15:04:54","date_gmt":"2025-09-02T15:04:54","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=472969"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=472969","title":{"rendered":"<span>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0411\u0414 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u044f\u0442\u043d\u0438\u0446\u0443<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7b2\/930\/960\/7b293096072b5447c821a3b3f0659b80.png\" width=\"1560\" height=\"880\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/7b2\/930\/960\/7b293096072b5447c821a3b3f0659b80.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7b2\/930\/960\/7b293096072b5447c821a3b3f0659b80.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u0435\u043d\u0438\u0441 \u041b\u0438\u043c\u0430\u0440\u0435\u0432, \u044f \u0440\u0443\u043a\u043e\u0432\u043e\u0436\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0432 \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 Uzum Tezkor. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0411\u0414, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043d\u0430\u0448\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u0432\u043e\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0438 \u043e\u043f\u0438\u0448\u0443 \u043f\u043e\u0434\u0445\u043e\u0434 \u043a \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0446\u0435\u043b\u043e\u043c. \u0412 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c PostgreSQL \u0432\u0435\u0440\u0441\u0438\u0438 14.15, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u044f \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b \u043d\u0430 \u043d\u0435\u0439, \u0438 \u0432\u0430\u0448\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0430\u0448\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438.<\/p>\n<h4>\u041e\u0433\u043b\u0430\u0432\u043b\u0435\u043d\u0438\u0435:<\/h4>\n<ol>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/uzum\/articles\/940624\/#1\" rel=\"noopener noreferrer nofollow\">\u0421\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/uzum\/articles\/940624\/#2\" rel=\"noopener noreferrer nofollow\">\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438\u00a0ad-hoc <\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/uzum\/articles\/940624\/#3\" rel=\"noopener noreferrer nofollow\">\u0414\u0435\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/uzum\/articles\/940624\/#4\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0443\u0441\u043b\u043e\u0432\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0438\u043b\u0438 IN vs JOIN<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/uzum\/articles\/940624\/#5\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u043a\u0438\u043d\u0435\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043d\u0430 \u0431\u044d\u043a\u0435\u043d\u0434<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/uzum\/articles\/940624\/#6\" rel=\"noopener noreferrer nofollow\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/uzum\/articles\/940624\/#7\" rel=\"noopener noreferrer nofollow\">\u0421\u043f\u0438\u0441\u043e\u043a \u043b\u0438\u0442\u0435\u0440\u0430\u0442\u0443\u0440\u044b \u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/a><\/p>\n<\/li>\n<\/ol>\n<p><a class=\"anchor\" name=\"1\" id=\"1\"><\/a><\/p>\n<h2>\u0421\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0dd\/78c\/42f\/0dd78c42f436a4167aa458e6fa7dbdb2.png\" width=\"1600\" height=\"900\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/0dd\/78c\/42f\/0dd78c42f436a4167aa458e6fa7dbdb2.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0dd\/78c\/42f\/0dd78c42f436a4167aa458e6fa7dbdb2.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0433\u043e\u0440\u043e\u0434\u0441\u043a\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u0447\u043d\u043e\u0439 \u0441\u0435\u0442\u0438, \u0433\u0434\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u0432 \u0438\u0437\u0434\u0430\u0442\u0435\u043b\u0435\u0439. \u041e\u0434\u043d\u0430\u0436\u0434\u044b \u043a \u043d\u0435\u043c\u0443 \u043f\u043e\u0434\u043e\u0448\u0451\u043b \u0442\u0438\u043c\u043b\u0438\u0434 \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439: \u00ab\u041c\u044b \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0438 \u0443\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043d\u043e\u0440\u043c\u0430\u0442\u0438\u0432\u044b \u043f\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043f\u043e\u0438\u0441\u043a\u0430 \u043a\u043d\u0438\u0433 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435, \u0438 \u0434\u0430\u0436\u0435 \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u043b\u0438 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u043f\u043e\u0440\u043e\u0433 \u043e\u0448\u0438\u0431\u043e\u043a \u0437\u0430 \u044d\u0442\u043e\u0442 \u043c\u0435\u0441\u044f\u0446 \u2014 \u043d\u0443\u0436\u043d\u043e \u0441\u0440\u043e\u0447\u043d\u043e \u0447\u0442\u043e-\u0442\u043e \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u043d\u044f\u0442\u044c\u00bb. \u00ab\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f\u00bb, \u2014 \u043e\u0442\u0432\u0435\u0442\u0438\u043b \u0413\u0435\u043e\u0440\u0433\u0438\u0439, \u0438 \u0441\u0440\u0430\u0437\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043b\u0441\u044f \u0438\u0437\u0443\u0447\u0430\u0442\u044c \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u0447\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b.<\/p>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0432 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 API, \u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u0441\u043e\u0431\u0440\u0430\u043b \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u043c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u0421\u0442\u0430\u043b\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u043a \u0411\u0414. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u0438\u0437\u0443\u0447\u0438\u043b \u0441\u0445\u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<pre><code class=\"sql\">CREATE TABLE catalogs (    id uuid primary key,    publisher_id uuid not null,    status enum('available', 'upcoming', 'archived') not null,    constraint catalogs_publisher_status_uniq unique (publisher_id, status) );  CREATE TABLE genres (    id uuid primary key,    name text not null,    catalog_id uuid not null );  create index idx_genres_catalog_id    on genres (catalog_id);  CREATE TABLE book_genre (    book_id uuid not null,    genre_id uuid not null );  create index idx_book_genre_hash_book_id    on book_genre using hash (book_id);  create index idx_book_genre_hash_genre_id    on book_genre using hash (genre_id);  create unique index book_genre_reverse_pkey    on book_genre (genre_id, book_id);  CREATE TABLE books (    id uuid primary key,    title text not null,    isbn text not null,    price int not null,    status enum('available', 'upcoming') not null,    publisher_id uuid not null,    catalog_id uuid not null );  CREATE INDEX idx_books_publisher_catalog_status    on books (publisher_id, catalog_id, status);  CREATE TABLE book_editions (    book_id uuid not null,    edition_id uuid not null );  create unique index book_edition_pkey    on book_editions (book_id, edition_id);  CREATE TABLE editions (    id uuid primary key,    title text not null,    isbn text not null,    price int not null,    max_copies int not null );  CREATE TABLE stockrooms (    id uuid primary key,    book_isbn text not null,    quantity int not null,    publisher_id uuid not null,    updated_at timestamptz not null,    constraint stockrooms_publisher_book_uniq unique (publisher_id, book_isbn) ); <\/code><\/pre>\n<p><a class=\"anchor\" name=\"2\" id=\"2\"><\/a><\/p>\n<h2>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 ad-hoc<\/h2>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/811\/ed9\/286\/811ed9286ce0ccc97298990e281d4cde.png\" width=\"1600\" height=\"900\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/811\/ed9\/286\/811ed9286ce0ccc97298990e281d4cde.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/811\/ed9\/286\/811ed9286ce0ccc97298990e281d4cde.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u043f\u0443\u0442\u0435\u043c API, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043f\u0430\u043b \u0432\u0437\u0433\u043b\u044f\u0434 \u0413\u0435\u043e\u0440\u0433\u0438\u044f, \u0431\u044b\u043b \/api\/v1\/books. \u041e\u043d \u0441\u043e\u0441\u0442\u043e\u044f\u043b \u0438\u0437 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0411\u0414:<\/p>\n<pre><code class=\"sql\">SELECT b.id, b.title, b.isbn, b.price FROM catalogs c JOIN genres g ON c.id = g.catalog_id JOIN book_genre bg ON bg.genre_id = g.id JOIN books b ON b.id = bg.book_id WHERE b.isbn IN (:isbns)   AND c.status = 'available';<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0447\u0430\u0441\u0442\u044f\u043c\u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0438\u0437\u0434\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"sql\">SELECT e.title, e.isbn, e.price FROM book_editions be JOIN editions e ON be.edition_id = e.id WHERE be.book_id IN (:book_ids);<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0438\u0441\u0438 \u0438\u0437\u0434\u0430\u043d\u0438\u0439 \u0431\u044b\u043b\u0438 \u043d\u0435 \u0443 \u0432\u0441\u0435\u0445 \u043a\u043d\u0438\u0433, \u0438 \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u043e\u043d\u0438 \u043c\u043e\u0433\u043b\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043f\u043e\u0441\u043b\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0440\u0430\u0441\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u0439, \u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u043f\u0440\u0438\u0448\u0435\u043b \u043a \u0432\u044b\u0432\u043e\u0434\u0443, \u0447\u0442\u043e \u043e\u043d \u043c\u043e\u0433 \u0431\u044b \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0438\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0435\u0433\u043e \u0443\u0431\u0440\u0430\u0442\u044c, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043f\u043e\u043b\u0435 \u0441\u043e \u0437\u043d\u0430\u043d\u0438\u0435\u043c \u043e \u0442\u043e\u043c, \u0435\u0441\u0442\u044c \u043b\u0438 \u0438\u0437\u0434\u0430\u043d\u0438\u0435 \u0443 \u043a\u043d\u0438\u0433\u0438. \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432 \u0441\u0445\u0435\u043c\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u0435 \u043c\u043e\u0433\u043b\u0438 \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u0432 \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435, \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043d\u043e\u0432\u044b\u0445.<\/p>\n<pre><code>ALTER TABLE books ADD COLUMN with_editions boolean NOT NULL DEFAULT true;<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0438\u0437\u0434\u0430\u043d\u0438\u044f \u0432 \u043a\u043e\u0434 \u0434\u043e \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0411\u0414. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0433\u043b\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0447\u0430\u0441\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p><a class=\"anchor\" name=\"3\" id=\"3\"><\/a><\/p>\n<h2>\u0414\u0435\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5ef\/d2f\/a2c\/5efd2fa2c4709d65007a06d4083db74b.png\" width=\"1600\" height=\"900\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/5ef\/d2f\/a2c\/5efd2fa2c4709d65007a06d4083db74b.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5ef\/d2f\/a2c\/5efd2fa2c4709d65007a06d4083db74b.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0417\u0430\u0442\u0435\u043c \u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u043f\u0435\u0440\u0435\u0448\u0435\u043b \u043a \u0437\u0430\u043f\u0440\u043e\u0441\u0443 \u043a\u043d\u0438\u0433:<\/p>\n<pre><code class=\"sql\">SELECT b.id, b.title, b.isbn, b.price FROM catalogs c      JOIN genres g ON c.id = g.catalog_id      JOIN book_genre bg ON bg.genre_id = g.id      JOIN books b ON b.id = bg.book_id WHERE b.isbn IN (:isbns)   AND c.status = 'available'   AND c.publisher_id = :publisher_id;<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b <code>EXPLAIN ANALYZE<\/code>:<\/p>\n<pre><code class=\"sql\">+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |QUERY PLAN                                                                                                                                                                 | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |Nested Loop  (cost=2.39..692.44 rows=2 width=93) (actual time=0.738..78.045 rows=500 loops=1)                                                                              | |  -&gt;  Nested Loop  (cost=0.71..42.29 rows=357 width=16) (actual time=0.542..12.698 rows=3280 loops=1)                                                                      | |      -&gt;  Nested Loop  (cost=0.71..17.55 rows=12 width=16) (actual time=0.455..1.183 rows=155 loops=1)                                                                     | |            -&gt;  Index Scan using catalog_publisher_status_uniq on catalogs c  (cost=0.29..2.50 rows=1 width=16) (actual time=0.049..0.051 rows=1 loops=1)                  | |                  Index Cond: ((publisher_id = '3b73167d-3ee3-4f09-a3af-c2989d76f04b'::uuid) AND (status = 'available'::catalog_status))                                   | |            -&gt;  Index Scan using idx_genres_catalog_id on genres g  (cost=0.42..14.93 rows=12 width=32) (actual time=0.402..1.085 rows=155 loops=1)                         | |                  Index Cond: (catalog_id = c.id)                                                                                                                          | |      -&gt;  Index Scan using idx_book_genre_hash_genre_id on book_genre bg  (cost=0.00..1.49 rows=57 width=32) (actual time=0.059..0.071 rows=21 loops=155)                   | |            Index Cond: (genre_id = g.id)                                                                                                                                  | |  -&gt;  Index Scan using books_pkey on books b  (cost=1.68..1.82 rows=1 width=93) (actual time=0.020..0.020 rows=0 loops=3280)                                                | |        Index Cond: (id = bg.book_id)                                                                                                                                      | |        Filter: ((isbn)::text = ANY ('{\u0442\u0443\u0442 500 isbn \u043a\u043d\u0438\u0433}'::text[]))                                                                                                       | |        Rows Removed by Filter: 1                                                                                                                                          | |Planning Time: 40.434 ms                                                                                                                                                   | |Execution Time: 78.272 ms                                                                                                                                                  | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+<\/code><\/pre>\n<p>\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e, \u043d\u0435 \u0443\u0432\u0435\u043d\u0447\u0430\u043b\u0430\u0441\u044c \u0443\u0441\u043f\u0435\u0445\u043e\u043c: \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u043b\u0443\u0447\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441. \u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u044f \u0441 \u043a\u043e\u043b\u043b\u0435\u0433\u0430\u043c\u0438 \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0438\u0434\u0435\u044f \u043e\u0431\u043e\u0433\u0430\u0442\u0438\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 books \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0442 <a href=\"https:\/\/www.postgresql.org\/docs\/current\/planner-stats.html\" rel=\"noopener noreferrer nofollow\">\u0441\u0435\u043b\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c<\/a> \u0437\u0430\u043f\u0440\u043e\u0441\u0430: \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c <a href=\"http:\/\/catalogs.id\" rel=\"noopener noreferrer nofollow\"><code>catalogs.id<\/code><\/a>, \u0442\u0430\u043a \u043a\u0430\u043a \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0436\u0430\u043d\u0440\u0430\u0445 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043d\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u0430\u0441\u044c, \u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 <code>genres<\/code> \u0438 <code>catalogs<\/code> \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0435\u0439 <code>books<\/code> \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u043b\u0438\u0441\u044c.<\/p>\n<p>\u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u043d\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u043b\u0438 \u0432 \u0442\u0440\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p>\u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 <code>catalog_id<\/code>:<\/p>\n<pre><code class=\"sql\">ALTER TABLE books ADD COLUMN catalog_id uuid null;<\/code><\/pre>\n<\/li>\n<li>\n<p>\u0447\u0430\u0441\u0442\u044f\u043c\u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e <code>books<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u043d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043a\u043d\u0438\u0433\u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u0442\u0430\u043a:<\/p>\n<pre><code class=\"sql\">SELECT b.id, b.title, b.isbn, b.price FROM catalogs c      JOIN books b ON b.catalog_id = c.id WHERE b.isbn IN (:isbns)   AND c.status = 'available'   AND c.publisher_id = :publisher_id;<\/code><\/pre>\n<p>\u0423\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0442\u0430\u0431\u043b\u0438\u0446 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<pre><code class=\"sql\">+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ |QUERY PLAN                                                                                                                                                   | +-------------------------------------------------------------------------------------------------------------------------------------------------------------+ |Nested Loop  (cost=2.10..55697.11 rows=1 width=93) (actual time=8.349..33.778 rows=500 loops=1)                                                               | |  -&gt;  Index Scan using catalog_publisher_status_uniq on catalogs c  (cost=0.29..2.51 rows=1 width=16) (actual time=0.016..0.019 rows=1 loops=1)               | |        Index Cond: ((publisher_id = '3b73167d-3ee3-4f09-a3af-c2989d76f04b'::uuid) AND (status = 'available'::catalog_status))                               | |  -&gt;  Index Scan using idx_books_publisher_catalog_status on books b  (cost=1.81..55694.59 rows=1 width=109) (actual time=8.328..33.659 rows=500 loops=1)     | |        Index Cond: (catalog_id = c.id)                                                                                                                      | |        Filter: ((isbn)::text = ANY ('{\u0442\u0443\u0442 500 isbn \u043a\u043d\u0438\u0433}'::text[]))                                                                                         | |        Rows Removed by Filter: 2780                                                                                                                         | |Planning Time: 35.097 ms                                                                                                                                     | |Execution Time: 33.880 ms                                                                                                                                     | +-------------------------------------------------------------------------------------------------------------------------------------------------------------+<\/code><\/pre>\n<p>\u0420\u0430\u0437\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443 \u043d\u043e\u0432\u044b\u043c \u0438 \u0441\u0442\u0430\u0440\u044b\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c:<\/p>\n<blockquote>\n<p>\u0411\u044b\u043b\u043e:<br \/>Planning Time: 40.434 ms<br \/>Execution Time: 78.272 ms<\/p>\n<p>\u0421\u0442\u0430\u043b\u043e:<br \/>Planning Time: 35.097 ms<br \/>Execution Time: 33.880 ms<\/p>\n<\/blockquote>\n<p>\u0421 \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0437\u0430\u0432\u0435\u043b\u0430 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u044b \u043d\u0430 \u0434\u043e\u043b\u0433\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 \u0411\u0414 \u0438 \u0441\u0442\u0430\u043b\u0430 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0443\u0437\u043d\u0430\u0432\u0430\u0442\u044c \u043e \u043f\u0440\u043e\u0441\u0435\u0434\u0430\u044e\u0449\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445.<\/p>\n<p><a class=\"anchor\" name=\"4\" id=\"4\"><\/a><\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0443\u0441\u043b\u043e\u0432\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0438\u043b\u0438 IN vs JOIN<\/h2>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u043c\u043e\u043d\u0438\u0442\u043e\u0440 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043d\u0430 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u0442\u043e\u043a\u043e\u0432, \u043a\u043e\u0433\u0434\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 <code>stocks<\/code> \u0434\u043e\u0441\u0442\u0438\u0433\u043b\u043e \u043e\u0442\u043c\u0435\u0442\u043a\u0438 \u0432 \u043e\u0434\u0438\u043d \u043c\u0438\u043b\u043b\u0438\u043e\u043d \u0437\u0430\u043f\u0438\u0441\u0435\u0439. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043b\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438. \u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u043f\u0440\u043e\u044f\u0432\u0438\u043b \u0438\u043d\u0438\u0446\u0438\u0430\u0442\u0438\u0432\u0443 \u0438 \u0437\u0430\u0431\u0440\u0430\u043b \u044d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u0443 \u0441\u0435\u0431\u0435. \u0421\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0443, \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0431\u044b\u043b\u0430 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435: \u043e\u043d \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b \u0443\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0432 100 \u043c\u0441 \u0432 98\u00a0% \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<pre><code class=\"sql\">SELECT s.id,        s.book_isbn,        s.quantity FROM stockrooms s WHERE s.publisher_id = :publisher_id   AND s.book_isbn IN (:isbns);<\/code><\/pre>\n<p>\u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u043d\u0435 \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0430\u0437 \u0437\u0430\u043d\u0438\u043c\u0430\u043b\u0441\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0435\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b <code>EXPLAIN ANALYZE<\/code>:<\/p>\n<pre><code class=\"sql\">+------------------------------------------------------------------------------------------------------------------------------------------------------------+ |QUERY PLAN                                                                                                                                                   | +------------------------------------------------------------------------------------------------------------------------------------------------------------+ |Index Scan using stockrooms_publisher_book_uniq on stockrooms s  (cost=0.56..846.94 rows=15 width=45) (actual time=1.237..19.237 rows=500 loops=1)           | |  Index Cond: ((publisher_id = '3b73167d-3ee3-4f09-a3af-c2989d76f04b'::uuid) AND ((book_isbn)::text = ANY ('{\u0442\u0443\u0442 500 isbn \u043a\u043d\u0438\u0433}'::text[])))                  | |Planning Time: 43.230 ms                                                                                                                                     | |Execution Time: 19.324 ms                                                                                                                                    | +------------------------------------------------------------------------------------------------------------------------------------------------------------+<\/code><\/pre>\n<p>\u0418\u0437 \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0431\u044b\u043b\u043e \u044f\u0441\u043d\u043e, \u0447\u0442\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0435\u0441\u0442\u044c \u0438 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 \u043d\u0438\u0445 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442. \u041f\u043e\u043f\u044b\u0442\u043a\u0438 \u043d\u0430\u0439\u0442\u0438 \u0434\u0440\u0443\u0433\u0438\u0435, \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0433\u043e\u0434\u043d\u044b\u0435 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043e\u0442\u0432\u0435\u0442\u0430 \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u043d\u0435 \u0443\u0432\u0435\u043d\u0447\u0430\u043b\u0438\u0441\u044c \u0443\u0441\u043f\u0435\u0445\u043e\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043b \u043f\u043e\u0438\u0441\u043a\u0438. \u0421\u0442\u0430\u0440\u0448\u0438\u0435 \u043a\u043e\u043b\u043b\u0435\u0433\u0438 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u0430\u043b\u0438, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c <code>IN<\/code> \u043d\u0430 <code>JOIN<\/code> \u0441 CTE, \u0447\u0442\u043e \u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u0438 \u043f\u043e\u043f\u044b\u0442\u0430\u043b\u0441\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c. \u041f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u0442\u0430\u043a\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441:<\/p>\n<pre><code class=\"sql\">WITH book_isbns AS (SELECT unnest(ARRAY [:book_isbns]) AS book_isbn) SELECT s.id,        s.book_isbn,        s.quantity FROM stockrooms s      JOIN book_isbns b ON s.book_isbn = b.book_isbn WHERE s.publisher_id = :publisher_id;<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0433\u043e\u043d \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u043f\u0440\u043e\u0434\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043a\u0430\u0437\u0430\u043b \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0435 \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u0432\u0435\u0440\u0441\u0438\u0435\u0439 \u0441 <code>IN<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u0440\u0435\u0448\u0438\u043b \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c <code>EXPLAIN ANALYZE<\/code> \u0434\u043b\u044f \u0432\u044b\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u0447\u0438\u043d:<\/p>\n<pre><code class=\"sql\">+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |QUERY PLAN                                                                                                                                                           | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |Nested Loop  (cost=0.56..1392.82 rows=7 width=45) (actual time=0.115..6.434 rows=500 loops=1)                                                                        | |  -&gt;  ProjectSet  (cost=0.00..2.52 rows=500 width=32) (actual time=0.002..0.058 rows=500 loops=1)                                                                    | |        -&gt;  Result  (cost=0.00..0.01 rows=1 width=0) (actual time=0.001..0.001 rows=1 loops=1)                                                                       | |  -&gt;  Index Scan using stockrooms_publisher_book_uniq on stockrooms s  (cost=0.56..2.77 rows=1 width=45) (actual time=0.012..0.012 rows=1 loops=500)                  | |        Index Cond: ((publisher_id = '3b73167d-3ee3-4f09-a3af-c2989d76f04b'::uuid) AND ((book_isbn)::text = (unnest('{\u0442\u0443\u0442 500 isbn \u043a\u043d\u0438\u0433}'::text[]))))                 | |Planning Time: 2.385 ms                                                                                                                                              | |Execution Time: 6.523 ms                                                                                                                                             | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------+<\/code><\/pre>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 <code>JOIN<\/code> \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u00ab\u0434\u0435\u0448\u0435\u0432\u043b\u0435\u00bb, \u0442\u043e \u0435\u0441\u0442\u044c \u0438\u043d\u0434\u0435\u043a\u0441 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e.<\/p>\n<p>\u041d\u043e \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0430\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430, \u0447\u0442\u043e \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435 \u0432\u043e \u0432\u0441\u0435\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445, \u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0447\u0435\u0440\u0435\u0437 <code>EXPLAIN ANALYZE<\/code> \u043e\u0431\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f.<\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435, \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443 \u043d\u043e\u0432\u044b\u043c \u0438 \u0441\u0442\u0430\u0440\u044b\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0430:<\/p>\n<blockquote>\n<p>\u0411\u044b\u043b\u043e:<br \/>Planning Time: 43.230 ms<br \/>Execution Time: 19.324 ms<\/p>\n<p>\u0421\u0442\u0430\u043b\u043e:<br \/>Planning Time: 2.385 ms<br \/>Execution Time: 6.523 ms<\/p>\n<\/blockquote>\n<p><a class=\"anchor\" name=\"5\" id=\"5\"><\/a><\/p>\n<h2>\u041d\u0430\u043a\u0438\u043d\u0435\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043d\u0430 \u0431\u044d\u043a\u0435\u043d\u0434<\/h2>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/26e\/8a0\/492\/26e8a0492408703401c16680b347fdc4.png\" width=\"1600\" height=\"900\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/26e\/8a0\/492\/26e8a0492408703401c16680b347fdc4.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/26e\/8a0\/492\/26e8a0492408703401c16680b347fdc4.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u043a\u0432\u0430\u0440\u0442\u0430\u043b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043e\u043f\u044f\u0442\u044c \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0430\u0441\u044c \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430. \u0412 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u0434\u0435\u043b\u043e \u0431\u044b\u043b\u043e \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u043f\u0443\u0442\u0435\u0439, \u0442\u043e\u0447\u043d\u0435\u0435, \u0432 \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u043c \u043f\u043e\u0438\u0441\u043a\u0435 \u043f\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0443 \u0438\u0437\u0434\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u043a\u043d\u0438\u0433:<\/p>\n<pre><code class=\"sql\">SELECT b.id,        b.title,        b.price      AS price,        b.isbn       AS isbn,        b.status     AS status FROM books b      JOIN catalogs c ON c.publisher_id IN (:publisher_ids)                     AND c.status = 'available' WHERE b.publisher_id IN (:publisher_ids)   AND b.catalog_id = c.id   AND b.status IN ('available', 'upcoming'); +-------------------------------------------------------------------------------------------------------------------------------------------------------+ |QUERY PLAN                                                                                                                                            | +-------------------------------------------------------------------------------------------------------------------------------------------------------+ |Nested Loop  (cost=0.84..13.93 rows=1 width=98) (actual time=0.056..15.414 rows=871 loops=1)                                                            | |  -&gt;  Index Scan using catalog_publisher_status_uniq on catalogs c  (cost=0.29..5.01 rows=2 width=16) (actual time=0.032..0.060 rows=2 loops=1)        | |        Index Cond: ((publisher_id = ANY ('{\u0442\u0443\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e id}'::uuid[])) AND (status = 'available'::catalog_status))                                  | |  -&gt;  Index Scan using idx_books_publisher_catalog_status on books b  (cost=0.56..4.45 rows=1 width=114) (actual time=0.022..7.619 rows=436 loops=2)| |        Index Cond: ((publisher_id = ANY ('{\u0442\u0443\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e id}'::uuid[])) AND (catalog_id = c.id))                                                     | |        Filter: (status = ANY ('{available,upcoming}'::book_status[]))                                                                                | |        Rows Removed by Filter: 6180                                                                                                                  | |Planning Time: 0.461 ms                                                                                                                               | |Execution Time: 15.496 ms                                                                                                                             | +-------------------------------------------------------------------------------------------------------------------------------------------------------+<\/code><\/pre>\n<p>\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u0434\u043e\u043b\u0433\u043e \u0434\u0443\u043c\u0430\u043b\u0430 \u0438 \u0440\u0435\u0448\u0438\u043b\u0430, \u0447\u0442\u043e \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0431\u044d\u043a\u0435\u043d\u0434\u0435, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0438 \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043c \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439.<\/p>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438, \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u043b\u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c\u044b\u0445 <code>publisher_id<\/code> \u043e\u0434\u043d\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c.<\/p>\n<pre><code class=\"sql\">SELECT b.id,        b.title,        b.price      AS price,        b.isbn       AS isbn,        b.status     AS status FROM books b      JOIN catalogs c ON c.publisher_id = :publisher_id                     AND c.status = 'available' WHERE b.publisher_id = :publisher_id   AND b.catalog_id = c.id   AND b.status IN ('available', 'upcoming');<\/code><\/pre>\n<p>\u041b\u043e\u0433\u0438\u0447\u043d\u043e, \u0447\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043b\u043e, \u0430 \u0435\u0441\u043b\u0438 \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0442\u044c \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0440\u0430\u0441\u0445\u043e\u0434\u043e\u0432 \u043d\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u0441\u0435\u0442\u0438, \u0442\u043e \u0434\u0430\u0436\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u043b\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u041d\u043e \u044d\u0442\u043e\u0442 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u0418 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0441\u0442\u0430\u043b\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 <code>publisher_id<\/code>, \u0430 \u0432\u0440\u0435\u043c\u044f \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u043b\u0438 \u043d\u0430 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u041f\u0430\u043a\u0435\u0442 database\/sql \u0438\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u043b \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e, \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0442\u0440\u043e\u043a \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043a\u043e\u043b\u043e\u043d\u043a\u0430\u0445 \u0432 \u043e\u0442\u0432\u0435\u0442\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0442\u0435\u0440\u044f\u0442\u044c \u0432 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 <code>scan<\/code>. \u041f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"sql\">rows, err := db.Query(` SELECT b.id,        b.title,        b.price      AS price,        b.isbn       AS isbn,        b.status     AS status FROM books b      JOIN catalogs c ON c.publisher_id = :publisher_id                     AND c.status = 'available' WHERE b.publisher_id = :publisher_id   AND b.catalog_id = c.id   AND b.status IN ('available', 'upcoming'); `) defer rows.Close()  for rows.Next() { \/\/ \u0442\u0443\u0442 10k \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439, \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0433\u043e\u0440\u0443\u0442\u0438\u043d \u043c\u044b \u043e\u0431\u043e\u0439\u0442\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043d\u0435 \u043c\u043e\u0436\u0435\u043c var id int var name string err := rows.Scan(&amp;id, &amp;name) \/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u0442\u0440\u043e\u043a\u0438 }<\/code><\/pre>\n<p>\u041d\u0430 \u0431\u044d\u043a\u0435\u043d\u0434\u0435 \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u0442\u0430\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e, \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 <code>publisher_id<\/code> \u0434\u043e \u0447\u0435\u0442\u044b\u0440\u0451\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043a \u0411\u0414 \u043f\u0440\u043e\u0441\u0442\u044b\u043c, \u043d\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u043b\u043e \u043b\u043e\u0433\u0438\u043a\u0443 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043d\u0430 \u0431\u044d\u043a\u0435\u043d\u0434\u0435. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u044d\u0442\u0438\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0413\u0435\u043e\u0440\u0433\u0438\u044e \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u0440\u0435\u0437\u0430\u0442\u044c \u0434\u043e 50 \u043c\u0441 \u043d\u0430 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u0432 \u0438\u0437 \u0411\u0414 \u0432 \u041e\u041f.<\/p>\n<p><a class=\"anchor\" name=\"6\" id=\"6\"><\/a><\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u042f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u043b\u0441\u044f \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043d\u0430\u0448\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u043e\u043d\u0438 \u0432\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u044f\u0442\u0441\u044f \u0438\u043b\u0438 \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u0432 \u0440\u0430\u0441\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u044f\u0445. \u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u2014 \u044d\u0442\u043e \u0437\u0430\u0434\u0430\u0447\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0448\u0438\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432, \u0438 \u0437\u043d\u0430\u043d\u0438\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0445\u043d\u0438\u043a \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0433\u0438\u0431\u0447\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442\u044c \u043a \u0440\u0435\u0448\u0435\u043d\u0438\u044e. <\/p>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0432\u044b\u0448\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432, \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438 \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f\u0445. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u0435\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0430\u0431\u043b\u0438\u0446 \u0447\u0435\u0440\u0435\u0437 \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u044e \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 matview. \u0410 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 ad-hoc \u0431\u0443\u0434\u0443\u0442 \u0441\u0432\u043e\u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0438 \u0435\u0433\u043e \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0430\u0448\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0443\u0440\u043e\u0432\u043d\u044f\u0445 \u0434\u0435\u0442\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u044d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u044c, \u0433\u0434\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442\u044c.<\/p>\n<p>\u0410 \u0435\u0441\u043b\u0438 \u0432\u044b \u043b\u044e\u0431\u0438\u0442\u0435 \u0438 \u0443\u043c\u0435\u0435\u0442\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0435 \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0443. \u0423 \u043d\u0430\u0441 \u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447.<\/p>\n<p><a class=\"anchor\" name=\"7\" id=\"7\"><\/a><\/p>\n<h2>\u0421\u043f\u0438\u0441\u043e\u043a \u043b\u0438\u0442\u0435\u0440\u0430\u0442\u0443\u0440\u044b \u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/h2>\n<ul>\n<li>\n<p><a href=\"https:\/\/explain.tensor.ru\/plan\/\" rel=\"noopener noreferrer nofollow\">https:\/\/explain.tensor.ru\/plan\/<\/a> \u2014 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f explain;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.percona.com\/blog\/sql-optimizations-in-postgresql-in-vs-exists-vs-any-all-vs-join\/\" rel=\"noopener noreferrer nofollow\">https:\/\/www.percona.com\/blog\/sql-optimizations-in-postgresql-in-vs-exists-vs-any-all-vs-join\/<\/a> \u2014 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e \u0441\u043f\u0438\u0441\u043a\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0434\u043b\u044f PostgreSQL 10;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/postgrespro\/articles\/662021\/\" rel=\"noopener noreferrer nofollow\">https:\/\/habr.com\/ru\/companies\/postgrespro\/articles\/662021\/<\/a> \u2014 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 JOIN;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/minervadb.xyz\/selectivity-and-cardinality-estimations-in-postgresql\/\" rel=\"noopener noreferrer nofollow\">https:\/\/minervadb.xyz\/selectivity-and-cardinality-estimations-in-postgresql\/<\/a> \u2014 \u043a\u043e\u0440\u043e\u0442\u043a\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u0440\u043e \u043e\u0446\u0435\u043d\u043a\u0443 \u043a\u0430\u0440\u0434\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u0441\u0435\u043b\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.postgresql.org\/docs\/current\/planner-stats.html\" rel=\"noopener noreferrer nofollow\">https:\/\/www.postgresql.org\/docs\/current\/planner-stats.html<\/a> \u2014 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u0440\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u0438 \u043f\u0440\u0438\u0447\u0435\u043c \u0442\u0443\u0442 \u0441\u0435\u043b\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.postgresql.org\/docs\/current\/row-estimation-examples.html\" rel=\"noopener noreferrer nofollow\">https:\/\/www.postgresql.org\/docs\/current\/row-estimation-examples.html<\/a> \u2014 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u0440\u043e \u043e\u0446\u0435\u043d\u043a\u0443 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u0442\u0440\u043e\u043a \u0447\u0435\u0440\u0435\u0437 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/exWargaming\/articles\/323354\/\" rel=\"noopener noreferrer nofollow\">https:\/\/habr.com\/ru\/companies\/exWargaming\/articles\/323354\/<\/a> \u2014 \u0438\u043d\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0447\u0438\u043d\u0430 \u043d\u0438\u0437\u043a\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043e\u0448\u0438\u0431\u043a\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0434\u0435\u0434\u043b\u043e\u043a\u0438.<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/940624\/\"> https:\/\/habr.com\/ru\/articles\/940624\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><\/figure>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u0435\u043d\u0438\u0441 \u041b\u0438\u043c\u0430\u0440\u0435\u0432, \u044f \u0440\u0443\u043a\u043e\u0432\u043e\u0436\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0432 \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 Uzum Tezkor. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0411\u0414, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043d\u0430\u0448\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u0432\u043e\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0438 \u043e\u043f\u0438\u0448\u0443 \u043f\u043e\u0434\u0445\u043e\u0434 \u043a \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0446\u0435\u043b\u043e\u043c. \u0412 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c PostgreSQL \u0432\u0435\u0440\u0441\u0438\u0438 14.15, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u044f \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b \u043d\u0430 \u043d\u0435\u0439, \u0438 \u0432\u0430\u0448\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0430\u0448\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438.<\/p>\n<h4>\u041e\u0433\u043b\u0430\u0432\u043b\u0435\u043d\u0438\u0435:<\/h4>\n<ol>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/uzum\/articles\/940624\/#1\" rel=\"noopener noreferrer nofollow\">\u0421\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/uzum\/articles\/940624\/#2\" rel=\"noopener noreferrer nofollow\">\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438\u00a0ad-hoc <\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/uzum\/articles\/940624\/#3\" rel=\"noopener noreferrer nofollow\">\u0414\u0435\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/uzum\/articles\/940624\/#4\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0443\u0441\u043b\u043e\u0432\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0438\u043b\u0438 IN vs JOIN<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/uzum\/articles\/940624\/#5\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u043a\u0438\u043d\u0435\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043d\u0430 \u0431\u044d\u043a\u0435\u043d\u0434<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/uzum\/articles\/940624\/#6\" rel=\"noopener noreferrer nofollow\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/uzum\/articles\/940624\/#7\" rel=\"noopener noreferrer nofollow\">\u0421\u043f\u0438\u0441\u043e\u043a \u043b\u0438\u0442\u0435\u0440\u0430\u0442\u0443\u0440\u044b \u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/a><\/p>\n<\/li>\n<\/ol>\n<p><a class=\"anchor\" name=\"1\" id=\"1\"><\/a><\/p>\n<h2>\u0421\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<figure class=\"full-width\"><\/figure>\n<p>\u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0433\u043e\u0440\u043e\u0434\u0441\u043a\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u0447\u043d\u043e\u0439 \u0441\u0435\u0442\u0438, \u0433\u0434\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u0432 \u0438\u0437\u0434\u0430\u0442\u0435\u043b\u0435\u0439. \u041e\u0434\u043d\u0430\u0436\u0434\u044b \u043a \u043d\u0435\u043c\u0443 \u043f\u043e\u0434\u043e\u0448\u0451\u043b \u0442\u0438\u043c\u043b\u0438\u0434 \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439: \u00ab\u041c\u044b \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0438 \u0443\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043d\u043e\u0440\u043c\u0430\u0442\u0438\u0432\u044b \u043f\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043f\u043e\u0438\u0441\u043a\u0430 \u043a\u043d\u0438\u0433 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435, \u0438 \u0434\u0430\u0436\u0435 \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u043b\u0438 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u043f\u043e\u0440\u043e\u0433 \u043e\u0448\u0438\u0431\u043e\u043a \u0437\u0430 \u044d\u0442\u043e\u0442 \u043c\u0435\u0441\u044f\u0446 \u2014 \u043d\u0443\u0436\u043d\u043e \u0441\u0440\u043e\u0447\u043d\u043e \u0447\u0442\u043e-\u0442\u043e \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u043d\u044f\u0442\u044c\u00bb. \u00ab\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f\u00bb, \u2014 \u043e\u0442\u0432\u0435\u0442\u0438\u043b \u0413\u0435\u043e\u0440\u0433\u0438\u0439, \u0438 \u0441\u0440\u0430\u0437\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043b\u0441\u044f \u0438\u0437\u0443\u0447\u0430\u0442\u044c \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u0447\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b.<\/p>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0432 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 API, \u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u0441\u043e\u0431\u0440\u0430\u043b \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u043c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u0421\u0442\u0430\u043b\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u043a \u0411\u0414. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u0438\u0437\u0443\u0447\u0438\u043b \u0441\u0445\u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<pre><code class=\"sql\">CREATE TABLE catalogs (    id uuid primary key,    publisher_id uuid not null,    status enum('available', 'upcoming', 'archived') not null,    constraint catalogs_publisher_status_uniq unique (publisher_id, status) );  CREATE TABLE genres (    id uuid primary key,    name text not null,    catalog_id uuid not null );  create index idx_genres_catalog_id    on genres (catalog_id);  CREATE TABLE book_genre (    book_id uuid not null,    genre_id uuid not null );  create index idx_book_genre_hash_book_id    on book_genre using hash (book_id);  create index idx_book_genre_hash_genre_id    on book_genre using hash (genre_id);  create unique index book_genre_reverse_pkey    on book_genre (genre_id, book_id);  CREATE TABLE books (    id uuid primary key,    title text not null,    isbn text not null,    price int not null,    status enum('available', 'upcoming') not null,    publisher_id uuid not null,    catalog_id uuid not null );  CREATE INDEX idx_books_publisher_catalog_status    on books (publisher_id, catalog_id, status);  CREATE TABLE book_editions (    book_id uuid not null,    edition_id uuid not null );  create unique index book_edition_pkey    on book_editions (book_id, edition_id);  CREATE TABLE editions (    id uuid primary key,    title text not null,    isbn text not null,    price int not null,    max_copies int not null );  CREATE TABLE stockrooms (    id uuid primary key,    book_isbn text not null,    quantity int not null,    publisher_id uuid not null,    updated_at timestamptz not null,    constraint stockrooms_publisher_book_uniq unique (publisher_id, book_isbn) ); <\/code><\/pre>\n<p><a class=\"anchor\" name=\"2\" id=\"2\"><\/a><\/p>\n<h2>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 ad-hoc<\/h2>\n<figure class=\"full-width\"><\/figure>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u043f\u0443\u0442\u0435\u043c API, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043f\u0430\u043b \u0432\u0437\u0433\u043b\u044f\u0434 \u0413\u0435\u043e\u0440\u0433\u0438\u044f, \u0431\u044b\u043b \/api\/v1\/books. \u041e\u043d \u0441\u043e\u0441\u0442\u043e\u044f\u043b \u0438\u0437 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0411\u0414:<\/p>\n<pre><code class=\"sql\">SELECT b.id, b.title, b.isbn, b.price FROM catalogs c JOIN genres g ON c.id = g.catalog_id JOIN book_genre bg ON bg.genre_id = g.id JOIN books b ON b.id = bg.book_id WHERE b.isbn IN (:isbns)   AND c.status = 'available';<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0447\u0430\u0441\u0442\u044f\u043c\u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0438\u0437\u0434\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"sql\">SELECT e.title, e.isbn, e.price FROM book_editions be JOIN editions e ON be.edition_id = e.id WHERE be.book_id IN (:book_ids);<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0438\u0441\u0438 \u0438\u0437\u0434\u0430\u043d\u0438\u0439 \u0431\u044b\u043b\u0438 \u043d\u0435 \u0443 \u0432\u0441\u0435\u0445 \u043a\u043d\u0438\u0433, \u0438 \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u043e\u043d\u0438 \u043c\u043e\u0433\u043b\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043f\u043e\u0441\u043b\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0440\u0430\u0441\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u0439, \u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u043f\u0440\u0438\u0448\u0435\u043b \u043a \u0432\u044b\u0432\u043e\u0434\u0443, \u0447\u0442\u043e \u043e\u043d \u043c\u043e\u0433 \u0431\u044b \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0438\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0435\u0433\u043e \u0443\u0431\u0440\u0430\u0442\u044c, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043f\u043e\u043b\u0435 \u0441\u043e \u0437\u043d\u0430\u043d\u0438\u0435\u043c \u043e \u0442\u043e\u043c, \u0435\u0441\u0442\u044c \u043b\u0438 \u0438\u0437\u0434\u0430\u043d\u0438\u0435 \u0443 \u043a\u043d\u0438\u0433\u0438. \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432 \u0441\u0445\u0435\u043c\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u0435 \u043c\u043e\u0433\u043b\u0438 \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u0432 \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435, \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043d\u043e\u0432\u044b\u0445.<\/p>\n<pre><code>ALTER TABLE books ADD COLUMN with_editions boolean NOT NULL DEFAULT true;<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0438\u0437\u0434\u0430\u043d\u0438\u044f \u0432 \u043a\u043e\u0434 \u0434\u043e \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0411\u0414. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0433\u043b\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0447\u0430\u0441\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p><a class=\"anchor\" name=\"3\" id=\"3\"><\/a><\/p>\n<h2>\u0414\u0435\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<figure class=\"full-width\"><\/figure>\n<p>\u0417\u0430\u0442\u0435\u043c \u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u043f\u0435\u0440\u0435\u0448\u0435\u043b \u043a \u0437\u0430\u043f\u0440\u043e\u0441\u0443 \u043a\u043d\u0438\u0433:<\/p>\n<pre><code class=\"sql\">SELECT b.id, b.title, b.isbn, b.price FROM catalogs c      JOIN genres g ON c.id = g.catalog_id      JOIN book_genre bg ON bg.genre_id = g.id      JOIN books b ON b.id = bg.book_id WHERE b.isbn IN (:isbns)   AND c.status = 'available'   AND c.publisher_id = :publisher_id;<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b <code>EXPLAIN ANALYZE<\/code>:<\/p>\n<pre><code class=\"sql\">+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |QUERY PLAN                                                                                                                                                                 | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |Nested Loop  (cost=2.39..692.44 rows=2 width=93) (actual time=0.738..78.045 rows=500 loops=1)                                                                              | |  -&gt;  Nested Loop  (cost=0.71..42.29 rows=357 width=16) (actual time=0.542..12.698 rows=3280 loops=1)                                                                      | |      -&gt;  Nested Loop  (cost=0.71..17.55 rows=12 width=16) (actual time=0.455..1.183 rows=155 loops=1)                                                                     | |            -&gt;  Index Scan using catalog_publisher_status_uniq on catalogs c  (cost=0.29..2.50 rows=1 width=16) (actual time=0.049..0.051 rows=1 loops=1)                  | |                  Index Cond: ((publisher_id = '3b73167d-3ee3-4f09-a3af-c2989d76f04b'::uuid) AND (status = 'available'::catalog_status))                                   | |            -&gt;  Index Scan using idx_genres_catalog_id on genres g  (cost=0.42..14.93 rows=12 width=32) (actual time=0.402..1.085 rows=155 loops=1)                         | |                  Index Cond: (catalog_id = c.id)                                                                                                                          | |      -&gt;  Index Scan using idx_book_genre_hash_genre_id on book_genre bg  (cost=0.00..1.49 rows=57 width=32) (actual time=0.059..0.071 rows=21 loops=155)                   | |            Index Cond: (genre_id = g.id)                                                                                                                                  | |  -&gt;  Index Scan using books_pkey on books b  (cost=1.68..1.82 rows=1 width=93) (actual time=0.020..0.020 rows=0 loops=3280)                                                | |        Index Cond: (id = bg.book_id)                                                                                                                                      | |        Filter: ((isbn)::text = ANY ('{\u0442\u0443\u0442 500 isbn \u043a\u043d\u0438\u0433}'::text[]))                                                                                                       | |        Rows Removed by Filter: 1                                                                                                                                          | |Planning Time: 40.434 ms                                                                                                                                                   | |Execution Time: 78.272 ms                                                                                                                                                  | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+<\/code><\/pre>\n<p>\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e, \u043d\u0435 \u0443\u0432\u0435\u043d\u0447\u0430\u043b\u0430\u0441\u044c \u0443\u0441\u043f\u0435\u0445\u043e\u043c: \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u043b\u0443\u0447\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441. \u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u044f \u0441 \u043a\u043e\u043b\u043b\u0435\u0433\u0430\u043c\u0438 \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0438\u0434\u0435\u044f \u043e\u0431\u043e\u0433\u0430\u0442\u0438\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 books \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0442 <a href=\"https:\/\/www.postgresql.org\/docs\/current\/planner-stats.html\" rel=\"noopener noreferrer nofollow\">\u0441\u0435\u043b\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c<\/a> \u0437\u0430\u043f\u0440\u043e\u0441\u0430: \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c <a href=\"http:\/\/catalogs.id\" rel=\"noopener noreferrer nofollow\"><code>catalogs.id<\/code><\/a>, \u0442\u0430\u043a \u043a\u0430\u043a \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0436\u0430\u043d\u0440\u0430\u0445 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043d\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u0430\u0441\u044c, \u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 <code>genres<\/code> \u0438 <code>catalogs<\/code> \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0435\u0439 <code>books<\/code> \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u043b\u0438\u0441\u044c.<\/p>\n<p>\u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u043d\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u043b\u0438 \u0432 \u0442\u0440\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p>\u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 <code>catalog_id<\/code>:<\/p>\n<pre><code class=\"sql\">ALTER TABLE books ADD COLUMN catalog_id uuid null;<\/code><\/pre>\n<\/li>\n<li>\n<p>\u0447\u0430\u0441\u0442\u044f\u043c\u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e <code>books<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u043d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043a\u043d\u0438\u0433\u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u0442\u0430\u043a:<\/p>\n<pre><code class=\"sql\">SELECT b.id, b.title, b.isbn, b.price FROM catalogs c      JOIN books b ON b.catalog_id = c.id WHERE b.isbn IN (:isbns)   AND c.status = 'available'   AND c.publisher_id = :publisher_id;<\/code><\/pre>\n<p>\u0423\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0442\u0430\u0431\u043b\u0438\u0446 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<pre><code class=\"sql\">+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ |QUERY PLAN                                                                                                                                                   | +-------------------------------------------------------------------------------------------------------------------------------------------------------------+ |Nested Loop  (cost=2.10..55697.11 rows=1 width=93) (actual time=8.349..33.778 rows=500 loops=1)                                                               | |  -&gt;  Index Scan using catalog_publisher_status_uniq on catalogs c  (cost=0.29..2.51 rows=1 width=16) (actual time=0.016..0.019 rows=1 loops=1)               | |        Index Cond: ((publisher_id = '3b73167d-3ee3-4f09-a3af-c2989d76f04b'::uuid) AND (status = 'available'::catalog_status))                               | |  -&gt;  Index Scan using idx_books_publisher_catalog_status on books b  (cost=1.81..55694.59 rows=1 width=109) (actual time=8.328..33.659 rows=500 loops=1)     | |        Index Cond: (catalog_id = c.id)                                                                                                                      | |        Filter: ((isbn)::text = ANY ('{\u0442\u0443\u0442 500 isbn \u043a\u043d\u0438\u0433}'::text[]))                           <\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-472969","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/472969","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=472969"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/472969\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=472969"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=472969"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=472969"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}