Sql 为什么';t此查询使用索引i';你创造了什么?

Sql 为什么';t此查询使用索引i';你创造了什么?,sql,database,postgresql,postgresql-9.5,Sql,Database,Postgresql,Postgresql 9.5,跑博士后9.5 SELECT events.id, events.start_time, events.host_id, events.title from events JOIN accountsevents ON accountsevents.events_id = events.id WHERE accountsevents.accounts_id = %(account_id)s OR events.host_id = %(account_id)s GROUP BY events.id

跑博士后9.5

SELECT events.id, events.start_time, events.host_id, events.title from events
JOIN accountsevents ON accountsevents.events_id = events.id
WHERE accountsevents.accounts_id = %(account_id)s OR events.host_id = %(account_id)s
GROUP BY events.id
ORDER BY start_time DESC
我有这个问题,postgres说成本超过10万美元。似乎太过分了。这是我仅有的一个没有利用我为每个表创建的索引的查询

Indexes:
    "events_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "events_host_id_fkey" FOREIGN KEY (host_id) REFERENCES accounts(id)
Referenced by:
    TABLE "accountsevents" CONSTRAINT "accountsevents_events_id_fkey" FOREIGN KEY (events_id) REFERENCES events(id)
    TABLE "eventsinterests" CONSTRAINT "eventsinterests_events_id_fkey" FOREIGN KEY (events_id) REFERENCES events(id)


Indexes:
    "accountsevents_pkey" PRIMARY KEY, btree (id, accounts_id, events_id)
Foreign-key constraints:
    "accountsevents_accounts_id_fkey" FOREIGN KEY (accounts_id) REFERENCES accounts(id)
    "accountsevents_events_id_fkey" FOREIGN KEY (events_id) REFERENCES events(id)
我觉得索引设置错误,或者我只是在查询中遗漏了一些东西。最初的序列扫描正在杀死它

添加了详细的解释

"Sort  (cost=124388.27..124390.10 rows=732 width=40) (actual time=1533.902..1533.928 rows=470 loops=1)"
"  Output: events.id, events.start_time, events.host_id, events.title"
"  Sort Key: events.start_time DESC"
"  Sort Method: quicksort  Memory: 66kB"
"  ->  HashAggregate  (cost=124346.12..124353.44 rows=732 width=40) (actual time=1533.658..1533.759 rows=470 loops=1)"
"        Output: events.id, events.start_time, events.host_id, events.title"
"        Group Key: events.id"
"        ->  Hash Join  (cost=4912.30..124344.29 rows=732 width=40) (actual time=56.671..1532.831 rows=971 loops=1)"
"              Output: events.id, events.start_time, events.host_id, events.title"
"              Hash Cond: (accountsevents.events_id = events.id)"
"              Join Filter: ((accountsevents.accounts_id = 1) OR (events.host_id = 1))"
"              Rows Removed by Join Filter: 2761882"
"              ->  Seq Scan on public.accountsevents  (cost=0.00..45228.52 rows=2762852 width=8) (actual time=0.005..466.094 rows=2762853 loops=1)"
"                    Output: accountsevents.events_id, accountsevents.accounts_id"
"              ->  Hash  (cost=2795.91..2795.91 rows=104191 width=40) (actual time=53.579..53.579 rows=104181 loops=1)"
"                    Output: events.id, events.start_time, events.host_id, events.title"
"                    Buckets: 65536  Batches: 4  Memory Usage: 2462kB"
"                    ->  Seq Scan on public.events  (cost=0.00..2795.91 rows=104191 width=40) (actual time=0.004..26.171 rows=104181 loops=1)"
"                          Output: events.id, events.start_time, events.host_id, events.title"
"Planning time: 0.201 ms"
"Execution time: 1534.024 ms"

没有索引可以帮助您进行此查询

问题是在
WHERE
条件中有
,因此在联接表之前不可能应用筛选器,这是索引可以帮助您的地方。试着用
替换
,看看PostgreSQL如何做得更好

这样,PostgreSQL必须计算整个连接,并且只能在之后过滤掉行–请参见连接过滤器删除的大量行

索引唯一可以使用的是嵌套循环联接,这将非常昂贵。所以我不认为有更好的方案来解决这个问题

您可以看到,PostgreSQL对行数的估计非常好,这通常表明PostgreSQL确实做了正确的事情

也许你可以用这样的查询做得更好

SELECT * FROM
   (SELECT ... FROM events JOIN accountsevents ON ...
       WHERE accountsevents.accounts_id = 1
    UNION
    SELECT ... FROM events JOIN accountsevents ON ...
       WHERE events.host_id = 1) sub
GROUP BY ... ORDER BY ...
但我不会打赌。

(注意:此查询在语义上略有不同,但在您的情况下可能并不重要。)

没有索引可以帮助您进行此查询

问题是在
WHERE
条件中有
,因此在联接表之前不可能应用筛选器,这是索引可以帮助您的地方。试着用
替换
,看看PostgreSQL如何做得更好

这样,PostgreSQL必须计算整个连接,并且只能在之后过滤掉行–请参见连接过滤器删除的大量行

索引唯一可以使用的是嵌套循环联接,这将非常昂贵。所以我不认为有更好的方案来解决这个问题

您可以看到,PostgreSQL对行数的估计非常好,这通常表明PostgreSQL确实做了正确的事情

也许你可以用这样的查询做得更好

SELECT * FROM
   (SELECT ... FROM events JOIN accountsevents ON ...
       WHERE accountsevents.accounts_id = 1
    UNION
    SELECT ... FROM events JOIN accountsevents ON ...
       WHERE events.host_id = 1) sub
GROUP BY ... ORDER BY ...
但我不会打赌。

(注意:此查询在语义上略有不同,但在您的情况下可能无关紧要。)

请回答您的问题,并添加使用
解释(分析,详细)
生成的执行计划。文本,我已经添加了解释看起来你有一个3列的索引,而你在查询中只使用了2列。索引需要全部3个字符。(id,accounts\u id,events\u id)我将使用id作为主键索引,并为accounts\u id和events\u id添加另一个索引。什么是
accountsevents.accounts\u id=%(account\u id)s
??看起来您正在尝试使用
类似于
?它是accounts表行的主键整数请回答您的问题并添加使用
解释(分析,详细)
生成的执行计划。文本,我已经添加了解释看起来你有一个3列的索引,而你在查询中只使用了2列。索引需要全部3个字符。(id,accounts\u id,events\u id)我将使用id作为主键索引,并为accounts\u id和events\u id添加另一个索引。什么是
accountsevents.accounts\u id=%(account\u id)s
??看起来您正在尝试使用类似于
?它是accounts表行的主键整数