Привет!
Сразу оговорюсь - всё проверял на свежеперестроенных индексах.
Дело в следующем: есть у меня табличка RssFeedItems в которой есть поле FeedId, являющееся по смыслу внешним ключём.
В этой таблице записи накапливаются в течении суток и в полночь 90% из них удаляется.
Кол-во записей от нескольких тысяч до сотен тысяч.
В процессе накапливания записей в таблице появляется огромное количество
записей зо значением NULL в поле FeedId (до 90%), т.е. индекс по внешнему ключу
получался очень плохой.
Погоняв базу анализистом мы покумекали и решили внешний ключ заменить на
триггеры + составной индекс.
Код таблицы и индекса такой:
CREATE TABLE "RssFeedItems" (
"Id" INTEGER NOT NULL PRIMARY KEY,
"FeedId" INTEGER,
...
);
CREATE INDEX "RssFeedItems_IDX2" ON "RssFeedItems" ("FeedId", "Id");
Есть ещё у меня связанная таблица, с которой мне часто надо джойнить первую:
CREATE TABLE "RssCacheElements" (
"Id" INTEGER NOT NULL PRIMARY KEY,
"RssFeedId" INTEGER,
"FeedDefinitionId" INTEGER NOT NULL,
...
);
ALTER TABLE "RssCacheElements" ADD CONSTRAINT FK_RSSCACHEELEMENTS_0 FOREIGN KEY ("FeedDefinitionId", "Type")
REFERENCES "FeedDefinitions" ("Id", "Type") ON DELETE CASCADE;
ALTER TABLE "RssCacheElements" ADD CONSTRAINT "FK_RssCacheElements_1" FOREIGN KEY ("RssFeedId")
REFERENCES "RssFeeds" ("Id") ON DELETE SET NULL;
Теперь интересное.
вот запрос не вызывающий никаких нареканий:
SELECT COUNT(*)
FROM "RssCacheElements" RCE
JOIN "RssFeedItems" RFI ON RCE."RssFeedId" = RFI."FeedId"
WHERE
RCE."FeedDefinitionId" = 279
-- OR RCE."FeedDefinitionId" = 280
PLAN JOIN (RCE INDEX (FK_RSSCACHEELEMENTS_0), RFI INDEX (RssFeedItems_IDX2))
Этот запрос извлекает 15 записей. При этом записей с RCE."FeedDefinitionId" = 280 не
существует, а записей с RCE."FeedDefinitionId" = 279 одна штука.
Теперь я раскоментирую -- OR RCE."FeedDefinitionId" = 280. В результате
получаю план
PLAN JOIN (RCE INDEX (FK_RSSCACHEELEMENTS_0, FK_RSSCACHEELEMENTS_0), RFI INDEX
(RssFeedItems_IDX2))
Но при этом из таблицы RssFeedItems получаю 57767 индексированных чтений !!!!
Пробую создать простой индекс:
CREATE INDEX "RssFeedItems_IDX3" ON "RssFeedItems" ("FeedId");
Запускаю:
SELECT COUNT(*)
FROM "RssCacheElements" RCE
JOIN "RssFeedItems" RFI ON RCE."RssFeedId" = RFI."FeedId"
WHERE
RCE."FeedDefinitionId" = 279
OR RCE."FeedDefinitionId" = 280
получаю план:
PLAN JOIN (RCE INDEX (FK_RSSCACHEELEMENTS_0, FK_RSSCACHEELEMENTS_0), RFI INDEX
(RssFeedItems_IDX3))
И при этом уже 15 индексированных чтений из RssFeedItems вместо 57767, как я и
ожидаю.
Вот, собственно, возникает вопрос, почему так и можно ли это пофиксить?