Привет!

Сразу оговорюсь - всё проверял на свежеперестроенных индексах.

Дело в следующем: есть у меня табличка 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, как я и 
ожидаю.

Вот, собственно, возникает вопрос, почему так и можно ли это пофиксить?

Ответить