Compare commits
2 Commits
fed7b2b637
...
bfae9ba8c7
Author | SHA1 | Date | |
---|---|---|---|
bfae9ba8c7 | |||
31f78d1f8b |
27
dev/database/DB page.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
aliases:
|
||||||
|
- страница
|
||||||
|
- страницы
|
||||||
|
- страница БД
|
||||||
|
- Страница БД
|
||||||
|
- странице бд
|
||||||
|
tags:
|
||||||
|
- maturity/🌱
|
||||||
|
date: 2024-11-04
|
||||||
|
---
|
||||||
|
В базе данных страница — это базовая единица хранения данных, используемая для организации таблиц и индексов. Она представляет собой фиксированный блок данных (обычно 8 килобайт в PostgreSQL, но размер может варьироваться) и содержит строки таблицы или фрагменты индексов. Когда база данных выполняет запрос, она обращается к страницам, чтобы получить нужные строки, и может считывать их из диска или из кэша, где часто используемые страницы уже загружены в память.
|
||||||
|
|
||||||
|
База данных работает поверх операционной системы и поэтому использует [[../fundamental/Страница|страницы ОС]] для хранения своих страниц данных. Когда СУБД загружает страницу базы данных из диска, операционная система выделяет ей одну или несколько страниц оперативной памяти. В результате страницы базы данных хранятся в страницах памяти ОС.
|
||||||
|
***
|
||||||
|
## Мета информация
|
||||||
|
**Область**:: [[../../meta/zero/00 Базы Данных|00 Базы Данных]]
|
||||||
|
**Родитель**:: [[../fundamental/Страница|Страница]]
|
||||||
|
**Источник**::
|
||||||
|
**Создана**:: [[2024-11-04]]
|
||||||
|
**Автор**::
|
||||||
|
### Дополнительные материалы
|
||||||
|
-
|
||||||
|
|
||||||
|
### Дочерние заметки
|
||||||
|
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||||
|
|
@ -6,6 +6,8 @@ tags:
|
|||||||
- maturity/🌱
|
- maturity/🌱
|
||||||
date: 2024-10-23
|
date: 2024-10-23
|
||||||
---
|
---
|
||||||
|
![[../../../meta/files/images/Pasted image 20241104202857.png]]
|
||||||
|
|
||||||
**Особенности:**
|
**Особенности:**
|
||||||
- Основан на работе [[../../fundamental/structure/B-tree|B-tree]] дерева.
|
- Основан на работе [[../../fundamental/structure/B-tree|B-tree]] дерева.
|
||||||
- Подходит для операций сравнения (`<`, `>`, `BETWEEN`), равенства (`=`) и сортировки.
|
- Подходит для операций сравнения (`<`, `>`, `BETWEEN`), равенства (`=`) и сортировки.
|
||||||
@ -27,7 +29,7 @@ CREATE INDEX idx_name ON table_name (column_name);
|
|||||||
**Создана**:: [[2024-10-23]]
|
**Создана**:: [[2024-10-23]]
|
||||||
**Автор**::
|
**Автор**::
|
||||||
### Дополнительные материалы
|
### Дополнительные материалы
|
||||||
-
|
- [Владимир Ситников — B-tree индексы в базах данных на примере PostgreSQL - YouTube](https://www.youtube.com/watch?v=mnEU2_cwE_s)
|
||||||
|
|
||||||
### Дочерние заметки
|
### Дочерние заметки
|
||||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||||
|
@ -13,7 +13,7 @@ parents:
|
|||||||
linked:
|
linked:
|
||||||
- "[[Репликация в PostgreSQL]]"
|
- "[[Репликация в PostgreSQL]]"
|
||||||
---
|
---
|
||||||
В журнал попадают физические изменения, т.е. обновления страничек. Есть [[../../fundamental/Страница|страница]] в памяти, на ней лежат какие-то данные, мы с ней что-то сделали – вот эту разницу мы записываем в журнал.
|
В журнал попадают физические изменения, т.е. обновления страничек. Есть [[../DB page|страница]] в памяти, на ней лежат какие-то данные, мы с ней что-то сделали – вот эту разницу мы записываем в журнал.
|
||||||
|
|
||||||
В WAL попадает всё: обновление таблиц, создание триггеров, создание хранимых процедур и так далее.
|
В WAL попадает всё: обновление таблиц, создание триггеров, создание хранимых процедур и так далее.
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ date: 2024-03-31
|
|||||||
- **Распухание индексов** (bloat) — это проблема увеличения размера индексов со временем, требующая переиндексации.
|
- **Распухание индексов** (bloat) — это проблема увеличения размера индексов со временем, требующая переиндексации.
|
||||||
|
|
||||||
- [[Создание индекса в PostgreSQL]]
|
- [[Создание индекса в PostgreSQL]]
|
||||||
- [[../Частичный индекс]]
|
- [[../Частичный индекс|Частичный индекс]]
|
||||||
- [[Составной индекс в PostgreSQL]]
|
- [[Составной индекс в PostgreSQL]]
|
||||||
|
|
||||||
**Типы индексов:**
|
**Типы индексов:**
|
||||||
@ -22,6 +22,10 @@ date: 2024-03-31
|
|||||||
- [[SP-GiST индекс в PostgreSQL|SP-GiST индекс]]
|
- [[SP-GiST индекс в PostgreSQL|SP-GiST индекс]]
|
||||||
- [[GIN индекс в PostgreSQL|GIN индекс]]
|
- [[GIN индекс в PostgreSQL|GIN индекс]]
|
||||||
- [[BRIN индекс в PostgreSQL|BRIN индекс]]
|
- [[BRIN индекс в PostgreSQL|BRIN индекс]]
|
||||||
|
|
||||||
|
**Влияние обновления строки на индекс**
|
||||||
|
- **Обновление индексированной колонки.** По факту мы добавляем новую запись в индекс, а старую забываем. Старая остается мертвым грузом (bloat), индекс распухает, его нужно убрать vacuum.
|
||||||
|
- **Обновление не индексированной колонки.** Если строка в таблице остается на той же [[../DB page|странице бд]], то есть было место на странице, то индекс не меняется. Если строка не помещается, то добавляется новая запись в индекс, а старая остается мертвым грузом (bloat), индекс распухает, его нужно убрать vacuum.
|
||||||
***
|
***
|
||||||
## Мета информация
|
## Мета информация
|
||||||
**Область**:: [[../../../meta/zero/00 PostgreSQL|00 PostgreSQL]]
|
**Область**:: [[../../../meta/zero/00 PostgreSQL|00 PostgreSQL]]
|
||||||
|
@ -26,13 +26,15 @@ EXPLAIN (FORMAT JSON) SELECT * FROM users WHERE id = 20;
|
|||||||
> [!NOTE] Analyze
|
> [!NOTE] Analyze
|
||||||
> `EXPLAIN` не выполняет сам запрос, поэтому результаты будут приблизительными. Для более точного анализа можно добавить ключевое слово `ANALYZE`, и тогда `EXPLAIN` также выполнит запрос.
|
> `EXPLAIN` не выполняет сам запрос, поэтому результаты будут приблизительными. Для более точного анализа можно добавить ключевое слово `ANALYZE`, и тогда `EXPLAIN` также выполнит запрос.
|
||||||
## Стоимость выполнения запроса (cost)
|
## Стоимость выполнения запроса (cost)
|
||||||
PostgreSQL использует условные единицы для обозначения стоимости выполнения запроса — `cost`. Один `cost` примерно соответствует времени, затраченному на извлечение одного блока данных размером 8 килобайт при последовательном сканировании (Seq Scan).
|
PostgreSQL использует условные единицы для обозначения стоимости выполнения запроса — `cost`. Один `cost` примерно соответствует времени, затраченному на извлечение одной [[../DB page|страницы]] при последовательном сканировании (Seq Scan).
|
||||||
|
|
||||||
Часто используются два значения `cost`:
|
Часто используются два значения `cost`:
|
||||||
- **Первое значение**: стоимость до начала получения первых результатов.
|
- **Первое значение**: стоимость до начала получения первых результатов.
|
||||||
- **Второе значение**: полная стоимость выполнения запроса.
|
- **Второе значение**: полная стоимость выполнения запроса.
|
||||||
|
|
||||||
Если оценочное значение `rows` слишком низкое по сравнению с фактическим количеством строк, это может означать, что статистика таблицы устарела. В таком случае необходимо выполнить `ANALYZE` для обновления статистики и улучшения качества планирования запросов.
|
Если оценочное значение `rows` слишком низкое по сравнению с фактическим количеством строк, это может означать, что статистика таблицы устарела. В таком случае необходимо выполнить `ANALYZE` для обновления статистики и улучшения качества планирования запросов.
|
||||||
|
|
||||||
|
Также PostgreSQL умеет считать количество обращений к диску. Для этого нужно добавить опцию `buffres`: `explain (analize, buffres)`. Это не время на чтение.
|
||||||
## Виды проходов по таблице и индексу
|
## Виды проходов по таблице и индексу
|
||||||
- **Seq Scan**: последовательный просмотр всей таблицы. Это наиболее медленный вариант и обычно нежелателен. Решение — добавить [[../Индекс базы данных|индекс]], чтобы ускорить выборку данных.
|
- **Seq Scan**: последовательный просмотр всей таблицы. Это наиболее медленный вариант и обычно нежелателен. Решение — добавить [[../Индекс базы данных|индекс]], чтобы ускорить выборку данных.
|
||||||
- **Index Scan**: использование [[../Индекс базы данных|индекса]] для просмотра таблицы.
|
- **Index Scan**: использование [[../Индекс базы данных|индекса]] для просмотра таблицы.
|
||||||
|
@ -5,7 +5,7 @@ tags:
|
|||||||
date: 2024-03-31
|
date: 2024-03-31
|
||||||
linked:
|
linked:
|
||||||
---
|
---
|
||||||
[[../Составные индексы в БД|Составные индексы]] в PostgreSQL позволяют ускорить выполнение запросов, в которых используются несколько колонок одновременно. Однако важно учитывать особенности их частичного использования.
|
[[../Составной индекс в БД|Составные индексы]] в PostgreSQL позволяют ускорить выполнение запросов, в которых используются несколько колонок одновременно. Однако важно учитывать особенности их частичного использования.
|
||||||
|
|
||||||
При выполнении запроса составной индекс может использоваться до первого неравенства включительно. Это означает, что при встрече оператора неравенства (`>`, `<`, `>=`, `<=`) индекс перестает быть эффективным для последующих колонок.
|
При выполнении запроса составной индекс может использоваться до первого неравенства включительно. Это означает, что при встрече оператора неравенства (`>`, `<`, `>=`, `<=`) индекс перестает быть эффективным для последующих колонок.
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ linked:
|
|||||||
***
|
***
|
||||||
## Мета информация
|
## Мета информация
|
||||||
**Область**:: [[../../../meta/zero/00 PostgreSQL|00 PostgreSQL]]
|
**Область**:: [[../../../meta/zero/00 PostgreSQL|00 PostgreSQL]]
|
||||||
**Родитель**:: [[../Составные индексы в БД|Составные индексы в БД]], [[Индекс в PostgreSQL]]
|
**Родитель**:: [[../Составной индекс в БД|Составной индекс в БД]], [[Индекс в PostgreSQL]]
|
||||||
**Источник**::
|
**Источник**::
|
||||||
**Автор**::
|
**Автор**::
|
||||||
**Создана**::
|
**Создана**::
|
||||||
|
24
dev/database/postgresql/Таблица в PostgreSQL.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
aliases:
|
||||||
|
- таблица
|
||||||
|
- таблице
|
||||||
|
tags:
|
||||||
|
- maturity/🌱
|
||||||
|
date: 2024-11-04
|
||||||
|
---
|
||||||
|
Таблица - это гомогенное множество кортежей.
|
||||||
|
|
||||||
|
Таблица разбивается на [[../DB page|страницы]].
|
||||||
|
***
|
||||||
|
## Мета информация
|
||||||
|
**Область**:: [[../../../meta/zero/00 PostgreSQL|00 PostgreSQL]]
|
||||||
|
**Родитель**::
|
||||||
|
**Источник**::
|
||||||
|
**Создана**:: [[2024-11-04]]
|
||||||
|
**Автор**::
|
||||||
|
### Дополнительные материалы
|
||||||
|
-
|
||||||
|
|
||||||
|
### Дочерние заметки
|
||||||
|
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||||
|
|
@ -48,7 +48,7 @@ date: 2024-10-11
|
|||||||
|
|
||||||
**Какие бывают индексы?**
|
**Какие бывают индексы?**
|
||||||
- **Уникальные и неуникальные.** Уникальные индексы обеспечивают уникальность значений в столбцах. Неуникальные индексы допускают повторяющиеся значения.
|
- **Уникальные и неуникальные.** Уникальные индексы обеспечивают уникальность значений в столбцах. Неуникальные индексы допускают повторяющиеся значения.
|
||||||
- **Простые и составные.** Простые индексы создаются для одного столбца, а [[Составные индексы в БД|составные]] — для нескольких столбцов.
|
- **Простые и составные.** Простые индексы создаются для одного столбца, а [[Составной индекс в БД|составные]] — для нескольких столбцов.
|
||||||
- **Кластерные и некластерные.** Кластерные индексы определяют физическое расположение данных на диске, а некластерные индексы хранят указатели на строки таблицы.
|
- **Кластерные и некластерные.** Кластерные индексы определяют физическое расположение данных на диске, а некластерные индексы хранят указатели на строки таблицы.
|
||||||
|
|
||||||
**Реализации:**
|
**Реализации:**
|
||||||
@ -67,9 +67,9 @@ date: 2024-10-11
|
|||||||
### Дочерние заметки
|
### Дочерние заметки
|
||||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||||
- [[Индекс в PostgreSQL]]
|
|
||||||
- [[Индекс в MySQL]]
|
- [[Индекс в MySQL]]
|
||||||
- [[Составные индексы в БД]]
|
- [[Индекс в PostgreSQL]]
|
||||||
- [[Покрывающий индекс]]
|
- [[Покрывающий индекс]]
|
||||||
|
- [[Составной индекс в БД]]
|
||||||
<!-- SerializedQuery END -->
|
<!-- SerializedQuery END -->
|
||||||
|
|
||||||
|
30
dev/database/Индекс в БД для мягкого удаления.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
aliases:
|
||||||
|
tags:
|
||||||
|
- maturity/🌱
|
||||||
|
- best-practices
|
||||||
|
date: 2024-11-05
|
||||||
|
---
|
||||||
|
Представьте, что вам нужно поддерживать уникальность данных, например, адресов электронной почты в таблице базы данных. Однако в таблице есть строки, [[../Tombstone|помеченные как удаленные]] с помощью поля `deleted_at`, и они также остаются в базе данных. В такой ситуации создание уникального индекса на поле с электронной почтой становится невозможным из-за дублирующихся значений. [[Частичный индекс|Частичный индекс]] решает эту проблему, позволяя включать в индекс только записи, которые не помечены как удаленные.
|
||||||
|
|
||||||
|
В PostgreSQL добавление уникального индекса для активных пользователей выглядит так:
|
||||||
|
```sql
|
||||||
|
CREATE UNIQUE INDEX users_email_uniq ON users (
|
||||||
|
email
|
||||||
|
) WHERE deleted_at IS NULL;
|
||||||
|
```
|
||||||
|
|
||||||
|
В этом случае строки, у которых `deleted_at` не задан, включаются в индекс, а остальные игнорируются, что делает индекс более компактным и эффективным.
|
||||||
|
***
|
||||||
|
## Мета информация
|
||||||
|
**Область**:: [[../../meta/zero/00 Базы Данных|00 Базы Данных]]
|
||||||
|
**Родитель**::
|
||||||
|
**Источник**::
|
||||||
|
**Создана**:: [[2024-11-05]]
|
||||||
|
**Автор**::
|
||||||
|
### Дополнительные материалы
|
||||||
|
-
|
||||||
|
|
||||||
|
### Дочерние заметки
|
||||||
|
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||||
|
|
@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
aliases:
|
||||||
|
tags:
|
||||||
|
- maturity/🌱
|
||||||
|
- hack
|
||||||
|
date: 2024-11-05
|
||||||
|
---
|
||||||
|
Если в таблице много записей с одинаковыми значениями (низкая [[Селективность колонки|селективность]]), и необходимо индексировать только записи с уникальными или более специфичными значениями, то можно использовать проблему низкой селективности для повышения эффективности запросов.
|
||||||
|
|
||||||
|
Когда менее селективные поля находятся в начале индекса, на одной [[DB page|странице]] в памяти базы данных группируются записи с одинаковыми значениями по этим полям. Это позволяет при поиске уникального значения считывать меньше [[DB page|страниц]] из памяти, что в некоторых случаях может улучшить производительность.
|
||||||
|
|
||||||
|
![[../../meta/files/images/Pasted image 20241105002717.png]]
|
||||||
|
***
|
||||||
|
## Мета информация
|
||||||
|
**Область**:: [[../../meta/zero/00 Базы Данных|00 Базы Данных]]
|
||||||
|
**Родитель**::
|
||||||
|
**Источник**::
|
||||||
|
**Создана**:: [[2024-11-05]]
|
||||||
|
**Автор**::
|
||||||
|
### Дополнительные материалы
|
||||||
|
-
|
||||||
|
|
||||||
|
### Дочерние заметки
|
||||||
|
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||||
|
|
@ -1,18 +1,17 @@
|
|||||||
---
|
---
|
||||||
aliases:
|
aliases:
|
||||||
- Составные индексы
|
- Составные индексы
|
||||||
|
- многоколоночный индекс
|
||||||
tags:
|
tags:
|
||||||
- maturity/🌱
|
- maturity/🌱
|
||||||
date: 2024-06-16
|
date: 2024-06-16
|
||||||
---
|
---
|
||||||
Составным называется индекс, который включает в себя сразу несколько полей. Он используется для повышения производительности запросов, которые фильтруют данные по нескольким колонкам одновременно.
|
Составной индекс — это индекс, включающий несколько полей, который используется для повышения производительности запросов, фильтрующих данные сразу по нескольким колонкам.
|
||||||
|
|
||||||
==В составных индексах важен порядок столбцов.== Порядок колонок в индексе влияет на его эффективность, и более [[Селективность колонки|селективные]] поля должны идти первыми, чтобы максимизировать производительность. SQL-запросы также должны следовать этому порядку для оптимального использования индекса.
|
Проще всего представить составной индекс не как последовательность индексов по отдельным колонкам, а как индекс по объединённым значениям этих колонок. Поэтому порядок столбцов в составном индексе имеет значение.== Он влияет на эффективность индекса, и поэтому чаще всего ==наиболее [[Селективность колонки|селективные]] поля следует располагать первыми== для максимальной производительности. ==SQL-запросы также должны учитывать этот порядок== для оптимального использования индекса.
|
||||||
|
|
||||||
При поиске по составному индексу значения колонок сравниваются по порядку, что делает порядок следования колонок критически важным для эффективности запросов.
|
Однако, есть исключительные ситуации из этого правила:
|
||||||
|
- [[Использование малоселективных полей для оптимизации чтения страниц]]
|
||||||
> [!WARNING] Количество параметров
|
|
||||||
> Составной индекс из 2-3 полей обычно считается нормальным и эффективно поддерживаемым. Если количество колонок в индексе превышает три, следует тщательно анализировать его использование, чтобы избежать излишней нагрузки на производительность.
|
|
||||||
|
|
||||||
**Преимущества:**
|
**Преимущества:**
|
||||||
- **Оптимизация дискового пространства**: ==Один составной индекс может заменить несколько простых индексов==, что экономит дисковое пространство.
|
- **Оптимизация дискового пространства**: ==Один составной индекс может заменить несколько простых индексов==, что экономит дисковое пространство.
|
||||||
@ -22,6 +21,12 @@ date: 2024-06-16
|
|||||||
- **Высокие накладные расходы при обновлении**: Каждый раз при вставке, обновлении или удалении данных, которые попадают в составной индекс, СУБД должна обновлять весь индекс, что может увеличивать время выполнения таких операций.
|
- **Высокие накладные расходы при обновлении**: Каждый раз при вставке, обновлении или удалении данных, которые попадают в составной индекс, СУБД должна обновлять весь индекс, что может увеличивать время выполнения таких операций.
|
||||||
- Старайтесь минимизировать использование неравенств в начале составных индексов, так как это может ограничить их применение для последующих колонок.
|
- Старайтесь минимизировать использование неравенств в начале составных индексов, так как это может ограничить их применение для последующих колонок.
|
||||||
|
|
||||||
|
> [!WARNING] Количество параметров
|
||||||
|
> Составной индекс из 2-3 полей обычно считается нормальным и эффективно поддерживаемым. Если количество колонок в индексе превышает три, следует тщательно анализировать его использование, чтобы избежать излишней нагрузки на производительность.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Создание составного индекса:
|
Создание составного индекса:
|
||||||
```sql
|
```sql
|
||||||
CREATE INDEX idx_example ON table_name (column_a, column_b);
|
CREATE INDEX idx_example ON table_name (column_a, column_b);
|
44
dev/database/Таблицы с колонкой статуса.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
aliases:
|
||||||
|
tags:
|
||||||
|
- maturity/🌱
|
||||||
|
- best-practices
|
||||||
|
date: 2024-11-05
|
||||||
|
---
|
||||||
|
Часто в приложениях есть таблицы, которые содержат колонку статуса (`state`). Обычно статус разделяет записи на "обработанные" и "необработанные". Индекс нам часто нужен именно по необработанным данным. Создавая [[Частичный индекс|частичный индекс]] только по необработанным данным, мы можем ускорить выполнение запроса и уменьшить размер индекса.
|
||||||
|
|
||||||
|
Возьмем типичную табличку, в которой есть какие-то статусы мы хотим находить данные по этому статусу.
|
||||||
|
|
||||||
|
![300](../../meta/files/images/Pasted%20image%2020240331095959.png)
|
||||||
|
![600](../../meta/files/images/Pasted%20image%2020240331100144.png)
|
||||||
|
|
||||||
|
Часто появляется желание сделать индекс по полю статуса:
|
||||||
|
|
||||||
|
![600](../../meta/files/images/Снимок%20экрана%202024-03-31%20в%2010.07.02.png)
|
||||||
|
|
||||||
|
Но по факту мы индексируем поле, которое имеет небольшую [селективность](../../dev/database/Селективность%20колонки.md). Такой индекс не эффективный.
|
||||||
|
|
||||||
|
Хороший вариант в данном случае:
|
||||||
|
![600](../../meta/files/images/Снимок%20экрана%202024-03-31%20в%2010.13.39.png)
|
||||||
|
|
||||||
|
Почти идеальный:
|
||||||
|
![600](../../meta/files/images/Снимок%20экрана%202024-03-31%20в%2010.15.06.png)
|
||||||
|
![500](../../meta/files/images/Pasted%20image%2020240331101612.png)
|
||||||
|
|
||||||
|
Идеальный. Совмещаем и [[postgresql/Составной индекс в PostgreSQL|составной индекс]] и частичный.
|
||||||
|
|
||||||
|
![[../../meta/files/images/Pasted image 20241021225124.png]]
|
||||||
|
|
||||||
|
***
|
||||||
|
## Мета информация
|
||||||
|
**Область**:: [[../../meta/zero/00 Базы Данных|00 Базы Данных]]
|
||||||
|
**Родитель**::
|
||||||
|
**Источник**::
|
||||||
|
**Создана**:: [[2024-11-05]]
|
||||||
|
**Автор**::
|
||||||
|
### Дополнительные материалы
|
||||||
|
-
|
||||||
|
|
||||||
|
### Дочерние заметки
|
||||||
|
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||||
|
|
@ -26,46 +26,8 @@ WHERE fk_id IS NOT NULL;
|
|||||||
|
|
||||||
**Когда использовать частичные индексы:**
|
**Когда использовать частичные индексы:**
|
||||||
- Когда необходимо уменьшить размер индекса за счёт исключения ненужных записей, что позволяет сэкономить место на диске и ускорить операции поиска.
|
- Когда необходимо уменьшить размер индекса за счёт исключения ненужных записей, что позволяет сэкономить место на диске и ускорить операции поиска.
|
||||||
- Когда таблица содержит большое количество записей с одинаковыми значениями (низкая [[Селективность колонки|селективность]]), и вам нужно индексировать только те записи, которые имеют уникальные или более специфичные значения.
|
- [[Использование малоселективных полей для оптимизации чтения страниц]]
|
||||||
- В ситуациях, когда индекс нужен для работы с данными, которые соответствуют определённому условию, например, только "необработанные" записи.
|
- [[Таблицы с колонкой статуса]]. В ситуациях, когда индекс нужен для работы с данными, которые соответствуют определённому условию, например, только "необработанные" записи.
|
||||||
## Применение частичных индексов
|
|
||||||
### Таблицы с колонкой статуса
|
|
||||||
Часто в приложениях есть таблицы, которые содержат колонку статуса (`state`). Обычно статус разделяет записи на "обработанные" и "необработанные". Индекс нам часто нужен именно по необработанным данным. Создавая частичный индекс только по необработанным данным, мы можем ускорить выполнение запроса и уменьшить размер индекса.
|
|
||||||
|
|
||||||
Возьмем типичную табличку, в которой есть какие-то статусы мы хотим находить данные по этому статусу.
|
|
||||||
|
|
||||||
![300](../../meta/files/images/Pasted%20image%2020240331095959.png)
|
|
||||||
![600](../../meta/files/images/Pasted%20image%2020240331100144.png)
|
|
||||||
|
|
||||||
Часто появляется желание сделать индекс по полю статуса:
|
|
||||||
|
|
||||||
![600](../../meta/files/images/Снимок%20экрана%202024-03-31%20в%2010.07.02.png)
|
|
||||||
|
|
||||||
Но по факту мы индексируем поле, которое имеет небольшую [селективность](../../dev/database/Селективность%20колонки.md). Такой индекс не эффективный.
|
|
||||||
|
|
||||||
Хороший вариант в данном случае:
|
|
||||||
![600](../../meta/files/images/Снимок%20экрана%202024-03-31%20в%2010.13.39.png)
|
|
||||||
|
|
||||||
Почти идеальный:
|
|
||||||
![600](../../meta/files/images/Снимок%20экрана%202024-03-31%20в%2010.15.06.png)
|
|
||||||
![500](../../meta/files/images/Pasted%20image%2020240331101612.png)
|
|
||||||
|
|
||||||
Идеальный. Совмещаем и [[postgresql/Составной индекс в PostgreSQL|составной индекс]] и частичный.
|
|
||||||
|
|
||||||
![[../../meta/files/images/Pasted image 20241021225124.png]]
|
|
||||||
|
|
||||||
### Для мягкого удаления
|
|
||||||
Представьте, что вам нужно поддерживать уникальность данных, например, адресов электронной почты в таблице базы данных. Однако в таблице есть строки, [[../Tombstone|помеченные как удаленные]] с помощью поля `deleted_at`, и они также остаются в базе данных. В такой ситуации создание уникального индекса на поле с электронной почтой становится невозможным из-за дублирующихся значений. Частичный индекс решает эту проблему, позволяя включать в индекс только записи, которые не помечены как удаленные.
|
|
||||||
|
|
||||||
В PostgreSQL добавление уникального индекса для активных пользователей выглядит так:
|
|
||||||
```sql
|
|
||||||
CREATE UNIQUE INDEX users_email_uniq ON users (
|
|
||||||
email
|
|
||||||
) WHERE deleted_at IS NULL;
|
|
||||||
```
|
|
||||||
|
|
||||||
В этом случае строки, у которых `deleted_at` не задан, включаются в индекс, а остальные игнорируются, что делает индекс более компактным и эффективным.
|
|
||||||
|
|
||||||
***
|
***
|
||||||
## Мета информация
|
## Мета информация
|
||||||
**Область**:: [[../../meta/zero/00 PostgreSQL|00 PostgreSQL]]
|
**Область**:: [[../../meta/zero/00 PostgreSQL|00 PostgreSQL]]
|
||||||
|
@ -12,9 +12,10 @@ date: 2024-01-29
|
|||||||
- Узел содержит множество элементов, что позволяет хранить больше данных в одном месте.
|
- Узел содержит множество элементов, что позволяет хранить больше данных в одном месте.
|
||||||
- Каждый узел представляет собой [[../Страница|страничку]] на диске, что снижает издержки на чтение.
|
- Каждый узел представляет собой [[../Страница|страничку]] на диске, что снижает издержки на чтение.
|
||||||
- В каждом узле есть ссылки на следующий и предыдущий узлы (характерно для B+tree).
|
- В каждом узле есть ссылки на следующий и предыдущий узлы (характерно для B+tree).
|
||||||
- В узлах дерева могут храниться сами данные или указатели на данные.
|
- В листьях дерева могут храниться сами данные или указатели на данные, то есть ссылаются на таблицу.
|
||||||
- Элементы в узле отсортированы, что делает поиск более эффективным и позволяет создавать деревья с небольшой высотой, тем самым уменьшая количество обращений к диску.
|
- Элементы в узле отсортированы, что делает поиск более эффективным и позволяет создавать деревья с небольшой высотой, тем самым уменьшая количество обращений к диску.
|
||||||
- Значения в узлах могут быть не уникальными.
|
- Значения в узлах могут быть не уникальными.
|
||||||
|
- Обычно высота дерева не больше 3-4 уровней.
|
||||||
## Параметр t
|
## Параметр t
|
||||||
Параметр `t` определяет количество элементов в узле дерева.
|
Параметр `t` определяет количество элементов в узле дерева.
|
||||||
- В каждом узле должно быть не менее `t-1` и не более `2t-1` ключей. Это правило важно для поддержания сбалансированности дерева, так как позволяет равномерно распределять элементы между узлами и поддерживать эффективную высоту дерева, что, в свою очередь, обеспечивает высокую производительность операций поиска.
|
- В каждом узле должно быть не менее `t-1` и не более `2t-1` ключей. Это правило важно для поддержания сбалансированности дерева, так как позволяет равномерно распределять элементы между узлами и поддерживать эффективную высоту дерева, что, в свою очередь, обеспечивает высокую производительность операций поиска.
|
||||||
@ -31,13 +32,23 @@ date: 2024-01-29
|
|||||||
- Поиск четных или нечетных чисел.
|
- Поиск четных или нечетных чисел.
|
||||||
- Поиск суффиксов (`LIKE '%c'` — неэффективно).
|
- Поиск суффиксов (`LIKE '%c'` — неэффективно).
|
||||||
## Поиск в B-tree
|
## Поиск в B-tree
|
||||||
Рассмотрим пример поиска значения `27`.
|
|
||||||
|
|
||||||
![](../../../meta/files/images/Pasted%20image%2020240129193115.png)
|
|
||||||
|
|
||||||
Значения в узлах могут быть не уникальными. Например, если значение `27` встречается дважды, поиск продолжается, переходя в следующий узел. Чтобы облегчить этот процесс, блоки на одном уровне связаны, создавая связный список.
|
|
||||||
|
|
||||||
Алгоритм поиска аналогичен [[Бинарное дерево поиска|бинарному дереву]], но выбор осуществляется из нескольких вариантов, а не из двух. Поиск выполняется за `O(t logt(n))`, но количество обращений к диску — `O(logt(n))`.
|
Алгоритм поиска аналогичен [[Бинарное дерево поиска|бинарному дереву]], но выбор осуществляется из нескольких вариантов, а не из двух. Поиск выполняется за `O(t logt(n))`, но количество обращений к диску — `O(logt(n))`.
|
||||||
|
|
||||||
|
Рассмотрим пример поиска значения `5`. Начинаем с корневого блока, он всегда один. 5 больше 1, но меньше 7, поэтому идем в левую часть индекса.
|
||||||
|
|
||||||
|
![[../../../meta/files/images/Pasted image 20241104203100.png]]
|
||||||
|
Видим, что 5 больше чем 4, поэтому идем по ссылке на 4
|
||||||
|
|
||||||
|
![[../../../meta/files/images/Pasted image 20241104203423.png]]
|
||||||
|
|
||||||
|
И там уже мы находим нашу 5.
|
||||||
|
![[../../../meta/files/images/Pasted image 20241104203446.png]]
|
||||||
|
|
||||||
|
А пятерка в свою очередь указывает на место в таблице, и мы можем достать оттуда данные.
|
||||||
|
|
||||||
|
![[../../../meta/files/images/Pasted image 20241104203517.png]]
|
||||||
|
|
||||||
|
Значения в узлах могут быть не уникальными. Например, если значение `5` встречается дважды, поиск продолжается, переходя в следующий узел. Чтобы облегчить этот процесс, блоки на одном уровне связаны, создавая связный список.
|
||||||
## Добавление в B-tree
|
## Добавление в B-tree
|
||||||
Представим, что нужно вставить значение `15` в уже существующее дерево.
|
Представим, что нужно вставить значение `15` в уже существующее дерево.
|
||||||
|
|
||||||
|
@ -3,12 +3,11 @@ aliases:
|
|||||||
- страницы
|
- страницы
|
||||||
- страниц
|
- страниц
|
||||||
- страничку
|
- страничку
|
||||||
|
- страницы ОС
|
||||||
|
- Страница ОС
|
||||||
tags:
|
tags:
|
||||||
- maturity/🌱
|
- maturity/🌱
|
||||||
date: 2024-09-17
|
date: 2024-09-17
|
||||||
zero-link:
|
|
||||||
parents:
|
|
||||||
linked:
|
|
||||||
---
|
---
|
||||||
Страница это непрерывный блок памяти фиксированного размера.
|
Страница это непрерывный блок памяти фиксированного размера.
|
||||||
|
|
||||||
@ -39,3 +38,6 @@ linked:
|
|||||||
|
|
||||||
### Дочерние заметки
|
### Дочерние заметки
|
||||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||||
|
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||||
|
- [[DB page]]
|
||||||
|
<!-- SerializedQuery END -->
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
aliases:
|
||||||
|
tags:
|
||||||
|
- maturity/🌱
|
||||||
|
date: 2024-11-04
|
||||||
|
---
|
||||||
|
```
|
||||||
|
L1 cache reference ......................... 0.5 ns
|
||||||
|
Branch mispredict ............................ 5 ns
|
||||||
|
L2 cache reference ........................... 7 ns
|
||||||
|
Mutex lock/unlock ........................... 25 ns
|
||||||
|
Main memory reference ...................... 100 ns
|
||||||
|
Compress 1K bytes with Zippy ............. 3,000 ns = 3 µs
|
||||||
|
Send 2K bytes over 1 Gbps network ....... 20,000 ns = 20 µs
|
||||||
|
SSD random read ........................ 150,000 ns = 150 µs
|
||||||
|
Read 1 MB sequentially from memory ..... 250,000 ns = 250 µs
|
||||||
|
Round trip within same datacenter ...... 500,000 ns = 0.5 ms
|
||||||
|
Read 1 MB sequentially from SSD* ..... 1,000,000 ns = 1 ms
|
||||||
|
Disk seek ........................... 10,000,000 ns = 10 ms
|
||||||
|
Read 1 MB sequentially from disk .... 20,000,000 ns = 20 ms
|
||||||
|
Send packet CA->Netherlands->CA .... 150,000,000 ns = 150 ms
|
||||||
|
```
|
||||||
|
|
||||||
|
![[../../meta/files/images/Pasted image 20241104204304.png]]
|
||||||
|
***
|
||||||
|
## Мета информация
|
||||||
|
**Область**:: [[../../meta/zero/00 Разработка|00 Разработка]]
|
||||||
|
**Родитель**::
|
||||||
|
**Источник**::
|
||||||
|
**Создана**:: [[2024-11-04]]
|
||||||
|
**Автор**::
|
||||||
|
### Дополнительные материалы
|
||||||
|
-
|
||||||
|
|
||||||
|
### Дочерние заметки
|
||||||
|
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||||
|
|
23
dev/Посмотренные доклады по разработке.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
aliases:
|
||||||
|
tags:
|
||||||
|
- maturity/🌱
|
||||||
|
date: 2024-11-05
|
||||||
|
---
|
||||||
|
-
|
||||||
|
- [[2024-11-05]]. [Владимир Ситников — B-tree индексы в базах данных на примере PostgreSQL - YouTube](https://www.youtube.com/watch?v=mnEU2_cwE_s)
|
||||||
|
- [[2024-11-05]]. [[../source/lecture/Доклад. Могут ли Virtual threads заменить Webflux|Доклад. Могут ли Virtual threads заменить Webflux]]
|
||||||
|
- [[2024-11-05]]. [[../source/lecture/Доклад. Индексы в PostgreSQL. Как понять, что создавать|Доклад. Индексы в PostgreSQL. Как понять, что создавать]]
|
||||||
|
***
|
||||||
|
## Мета информация
|
||||||
|
**Область**:: [[../source/00 Источники|00 Источники]]
|
||||||
|
**Родитель**::
|
||||||
|
**Источник**::
|
||||||
|
**Создана**:: [[2024-11-05]]
|
||||||
|
**Автор**::
|
||||||
|
### Дополнительные материалы
|
||||||
|
-
|
||||||
|
|
||||||
|
### Дочерние заметки
|
||||||
|
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||||
|
|
1
index.md
@ -79,6 +79,7 @@ enableToc: false
|
|||||||
|
|
||||||
**По типу контента:**
|
**По типу контента:**
|
||||||
#content/opinion - Мое субъективное мнение по какой-то теме, по какому-то вопросу.
|
#content/opinion - Мое субъективное мнение по какой-то теме, по какому-то вопросу.
|
||||||
|
#content/problem - Заметки, которые появились для решения проблем, с которыми я сталкивался.
|
||||||
#content/checklist - Различные полезные чек-листы.
|
#content/checklist - Различные полезные чек-листы.
|
||||||
#type/archive - Архивные заметки. Их обновление не планируется, так как тема потеряла для меня интерес.
|
#type/archive - Архивные заметки. Их обновление не планируется, так как тема потеряла для меня интерес.
|
||||||
|
|
||||||
|
BIN
meta/files/images/Pasted image 20241104202857.png
Normal file
After Width: | Height: | Size: 614 KiB |
BIN
meta/files/images/Pasted image 20241104203100.png
Normal file
After Width: | Height: | Size: 601 KiB |
BIN
meta/files/images/Pasted image 20241104203423.png
Normal file
After Width: | Height: | Size: 637 KiB |
BIN
meta/files/images/Pasted image 20241104203446.png
Normal file
After Width: | Height: | Size: 668 KiB |
BIN
meta/files/images/Pasted image 20241104203517.png
Normal file
After Width: | Height: | Size: 716 KiB |
BIN
meta/files/images/Pasted image 20241104204304.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
meta/files/images/Pasted image 20241105002717.png
Normal file
After Width: | Height: | Size: 810 KiB |
BIN
meta/files/images/comp/Pasted image 20241104202857.png
Normal file
After Width: | Height: | Size: 130 KiB |
@ -0,0 +1 @@
|
|||||||
|
f7acfd614fc477ebff10b74de2d716ed
|
BIN
meta/files/images/comp/Pasted image 20241104203100.png
Normal file
After Width: | Height: | Size: 121 KiB |
@ -0,0 +1 @@
|
|||||||
|
933b38087b1601e6864908001b041df5
|
BIN
meta/files/images/comp/Pasted image 20241104203423.png
Normal file
After Width: | Height: | Size: 129 KiB |
@ -0,0 +1 @@
|
|||||||
|
e82618e260f128c6cd048561af961e44
|
BIN
meta/files/images/comp/Pasted image 20241104203446.png
Normal file
After Width: | Height: | Size: 134 KiB |
@ -0,0 +1 @@
|
|||||||
|
611a31d49324aab65ef65af0d5710ad7
|
BIN
meta/files/images/comp/Pasted image 20241104203517.png
Normal file
After Width: | Height: | Size: 141 KiB |
@ -0,0 +1 @@
|
|||||||
|
bf46eb6f9a60ee2907f1030ceb9ce2cf
|
BIN
meta/files/images/comp/Pasted image 20241104204304.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
@ -0,0 +1 @@
|
|||||||
|
035fd400699ca217a05fbe1e517d12a8
|
BIN
meta/files/images/comp/Pasted image 20241105002717.png
Normal file
After Width: | Height: | Size: 207 KiB |
@ -0,0 +1 @@
|
|||||||
|
b46e120ce165d4f7a8ea5df8c60a4d31
|
BIN
meta/files/images/webp/Pasted image 20241104202857.webp
Normal file
After Width: | Height: | Size: 67 KiB |
@ -0,0 +1 @@
|
|||||||
|
f7acfd614fc477ebff10b74de2d716ed
|
BIN
meta/files/images/webp/Pasted image 20241104203100.webp
Normal file
After Width: | Height: | Size: 70 KiB |
@ -0,0 +1 @@
|
|||||||
|
933b38087b1601e6864908001b041df5
|
BIN
meta/files/images/webp/Pasted image 20241104203423.webp
Normal file
After Width: | Height: | Size: 73 KiB |
@ -0,0 +1 @@
|
|||||||
|
e82618e260f128c6cd048561af961e44
|
BIN
meta/files/images/webp/Pasted image 20241104203446.webp
Normal file
After Width: | Height: | Size: 74 KiB |
@ -0,0 +1 @@
|
|||||||
|
611a31d49324aab65ef65af0d5710ad7
|
BIN
meta/files/images/webp/Pasted image 20241104203517.webp
Normal file
After Width: | Height: | Size: 80 KiB |
@ -0,0 +1 @@
|
|||||||
|
bf46eb6f9a60ee2907f1030ceb9ce2cf
|
@ -0,0 +1 @@
|
|||||||
|
035fd400699ca217a05fbe1e517d12a8
|
BIN
meta/files/images/webp/Pasted image 20241105002717.webp
Normal file
After Width: | Height: | Size: 102 KiB |
@ -0,0 +1 @@
|
|||||||
|
b46e120ce165d4f7a8ea5df8c60a4d31
|
@ -19,6 +19,7 @@ title: PostgreSQL
|
|||||||
- Изменение данных не заменяет строчку физически в памяти, а добавляет новую версию строки. Устаревшие строки через какое-то время помечаются и в них пишутся новые данные.
|
- Изменение данных не заменяет строчку физически в памяти, а добавляет новую версию строки. Устаревшие строки через какое-то время помечаются и в них пишутся новые данные.
|
||||||
- Если транзакции нужно выполнить операцию с данными, с которыми работает другая транзакция, то она может встать в очередь.
|
- Если транзакции нужно выполнить операцию с данными, с которыми работает другая транзакция, то она может встать в очередь.
|
||||||
- В логи попадают не все запросы. Это настраивается конфигурационными параметрами. Если логировать все запросы, то просядет производительность.
|
- В логи попадают не все запросы. Это настраивается конфигурационными параметрами. Если логировать все запросы, то просядет производительность.
|
||||||
|
- Типичный размер [[../../dev/database/DB page|страницы]] 8 килобайт. На страницу помещается ~ 100 записей.
|
||||||
|
|
||||||
## Дополнительные материалы
|
## Дополнительные материалы
|
||||||
- [pg_utils](../../dev/database/postgresql/pg_utils.md)
|
- [pg_utils](../../dev/database/postgresql/pg_utils.md)
|
@ -35,7 +35,7 @@ linked:
|
|||||||
|
|
||||||
## Заметки
|
## Заметки
|
||||||
- Классические СУБД хранят данные в двух местах: на диске и в памяти.
|
- Классические СУБД хранят данные в двух местах: на диске и в памяти.
|
||||||
- [[../../dev/fundamental/Страница|Страница]] модифицируется сначала в оперативной памяти, потом попадает на диск.
|
- [[../../dev/database/DB page|Страница БД]] модифицируется сначала в оперативной памяти, потом попадает на диск.
|
||||||
- ![](Pasted%20image%2020240531082744.png)
|
- ![](Pasted%20image%2020240531082744.png)
|
||||||
- Часто думают, что реляционная таблица — это массив. Некоторые даже думают, что это двумерный массив. На самом деле, это гораздо более сложная штука. Это мультимножество – набор определенного сорта кортежей, над которым не задано порядка. В SQL-таблице нет порядка. Это важно. И, как результат, когда вы делаете SELECT* из БД (просканировать все записи), результат выполнения запроса может меняться – строчки могут быть в одном порядке, а могут и в другом. Про это нужно помнить.
|
- Часто думают, что реляционная таблица — это массив. Некоторые даже думают, что это двумерный массив. На самом деле, это гораздо более сложная штука. Это мультимножество – набор определенного сорта кортежей, над которым не задано порядка. В SQL-таблице нет порядка. Это важно. И, как результат, когда вы делаете SELECT* из БД (просканировать все записи), результат выполнения запроса может меняться – строчки могут быть в одном порядке, а могут и в другом. Про это нужно помнить.
|
||||||
- Профиль нагрузки на реляционную базу данных выглядит следующим образом: 80% запросов это чтение, 20% запросов это запись. Если запросов на запись больше, то возможно реляционная база данных вам не подходит.
|
- Профиль нагрузки на реляционную базу данных выглядит следующим образом: 80% запросов это чтение, 20% запросов это запись. Если запросов на запись больше, то возможно реляционная база данных вам не подходит.
|
||||||
|
@ -4,11 +4,15 @@ tags:
|
|||||||
date: 2024-10-02
|
date: 2024-10-02
|
||||||
---
|
---
|
||||||
Здесь собраны ссылки на заметки, в которых я анализирую прочитанный/просмотренный материал.
|
Здесь собраны ссылки на заметки, в которых я анализирую прочитанный/просмотренный материал.
|
||||||
|
|
||||||
|
- [[../dev/Посмотренные доклады по разработке|Посмотренные доклады по разработке]]
|
||||||
|
-
|
||||||
## Доклады
|
## Доклады
|
||||||
<!-- QueryToSerialize: LIST FROM #type/source/lecture SORT Создана DESC -->
|
<!-- QueryToSerialize: LIST FROM #type/source/lecture SORT Создана DESC -->
|
||||||
<!-- SerializedQuery: LIST FROM #type/source/lecture SORT Создана DESC -->
|
<!-- SerializedQuery: LIST FROM #type/source/lecture SORT Создана DESC -->
|
||||||
- [[Доклад. Могут ли Virtual threads заменить Webflux]]
|
- [[Доклад. Могут ли Virtual threads заменить Webflux]]
|
||||||
- [[Доклад]]
|
- [[Доклад]]
|
||||||
|
- [[Доклад. Индексы в PostgreSQL. Как понять, что создавать]]
|
||||||
<!-- SerializedQuery END -->
|
<!-- SerializedQuery END -->
|
||||||
## Статьи
|
## Статьи
|
||||||
<!-- QueryToSerialize: LIST FROM #type/source/article SORT Создана DESC -->
|
<!-- QueryToSerialize: LIST FROM #type/source/article SORT Создана DESC -->
|
||||||
|