Ответ
Да, PostgreSQL не только разрешает, но и часто требует создания индексов по неуникальным полям для ускорения запросов. Индекс на неуникальном поле (например, category_id, status, created_at) не накладывает ограничение уникальности, но значительно ускоряет операции SELECT, UPDATE, DELETE с условиями WHERE, JOIN, а также ORDER BY по этому полю.
Например, в Node.js-приложении для таблицы заказов (orders) индекс по полю user_id (которое явно не уникально) был критически важен:
CREATE INDEX idx_orders_user_id ON orders(user_id);
Этот индекс делает мгновенным запрос на получение всех заказов пользователя, который часто используется в API:
SELECT * FROM orders WHERE user_id = 12345 ORDER BY created_at DESC;
Для такого запроса можно создать и составной индекс для еще большей эффективности:
CREATE INDEX idx_orders_user_created ON orders(user_id, created_at DESC);
При работе с ORM Sequelize в Node.js я указывал такие индексы прямо в определении модели:
// Модель Order
user_id: {
type: DataTypes.INTEGER,
references: { model: 'Users', key: 'id' },
index: true // Создаст некластеризованный индекс B-tree
}
Важно помнить, что индексы ускоряют чтение, но замедляют операции записи (INSERT, UPDATE, DELETE), так как сам индекс也需要 обновлять. Поэтому их добавляют обдуманно, основываясь на паттернах запросов приложения.
Ответ 18+ 🔞
Слушай, а ведь многие думают, что индекс в базе — это только чтобы уникальность проверить. Ну, типа, PRIMARY KEY или UNIQUE. А на самом деле, ёпта, это же главный инструмент, чтобы запросы не тормозили как старая телега! PostgreSQL вообще-то не просто разрешает, а часто прям требует создавать индексы по полям, где значения повторяются. Ну, типа по category_id или status. Уникальности там ноль, но зато скорость выборки — овердохуища!
Вот представь: у тебя в Node.js-приложении таблица заказов, orders. Каждый юзер может иметь дохуя заказов, так что поле user_id — точно не уникальное. Так вот, если на него индекс не повесить, то запрос «покажи все заказы пользователя 12345» будет работать так медленно, что волнение ебать! База будет полную таблицу сканировать, как будто ищет иголку в стоге сена. А с индексом — хуй с горы, мгновенно!
CREATE INDEX idx_orders_user_id ON orders(user_id);
После этого твой частый API-запрос станет летать:
SELECT * FROM orders WHERE user_id = 12345 ORDER BY created_at DESC;
Но и это ещё не всё, хитрая жопа! Можно сделать ещё круче — создать составной индекс. Это когда индекс сразу по двум полям, которые часто вместе в запросах мелькают. Например, вот так:
CREATE INDEX idx_orders_user_created ON orders(user_id, created_at DESC);
Теперь запрос, который и фильтрует по юзеру, и сортирует по дате, будет просто пизда рулю! База данных уже всё в нужном порядке держит.
Когда я с ORM Sequelize в Node.js работал, я эти индексы прямо в модели прописывал, чтобы не забыть. Выглядит это примерно так:
// Модель Order
user_id: {
type: DataTypes.INTEGER,
references: { model: 'Users', key: 'id' },
index: true // Создаст некластеризованный индекс B-tree
}
Но, чувак, тут главное — не переборщить. Индексы — они как мощный допинг: читать помогают охуенно, а вот писать (INSERT, UPDATE, DELETE) начинают тормозить. Потому что каждый раз, когда ты новую запись вставляешь, база должна не только в таблицу её запихнуть, но и во все связанные индексы. Так что добавлять их нужно с умом, глядя на то, какие запросы у тебя в приложении самые частые и медленные. А то наклепаешь индексов на каждое поле — и потом удивляешься, почему новая запись вставляется целую секунду. В общем, доверия ебать ноль к слепой индексации, думать головой надо!