我的数据库查询时间很慢(到目前为止都在本地测试过)并且不确定如何进行。数据库本身有44个表,其中一些表有超过100万条记录(主要是电影,女演员和演员表)。
该表是通过JDB使用IMDB上的平面文件制作的。我即将展示的SQL查询来自该程序(也经历了非常慢的搜索时间)。我试图尽可能多地包含信息,例如查询计划等。
"QUERY PLAN"<br />
"HashAggregate (cost=46492.52..46493.50 rows=98 width=46)"<br />
" Output: public.movies.title, public.movies.movieid, public.movies.year"<br />
" -> Append (cost=39094.17..46491.79 rows=98 width=46)"<br />
" -> HashAggregate (cost=39094.17..39094.87 rows=70 width=46)"<br />
" Output: public.movies.title, public.movies.movieid, public.movies.year"<br />
" -> Seq Scan on movies (cost=0.00..39093.65 rows=70 width=46)"<br />
" Output: public.movies.title, public.movies.movieid, public.movies.year"<br />
" Filter: (((title)::text ~~* '%Babe%'::text) AND ((title)::text !~~* '""%}'::text))"<br />
" -> Nested Loop (cost=0.00..7395.94 rows=28 width=46)"<br />
" Output: public.movies.title, public.movies.movieid, public.movies.year"<br />
" -> Seq Scan on akatitles (cost=0.00..7159.24 rows=28 width=4)"<br />
" Output: akatitles.movieid, akatitles.language, akatitles.title, <akatitles.addition"<br />
" Filter: (((title)::text ~~* '%Babe%'::text) AND ((title)::text !~~* '""%}'::text))"<br />
" -> Index Scan using movies_pkey on movies (cost=0.00..8.44 rows=1 width=46)"<br />
" Output: public.movies.movieid, public.movies.title, public.movies.year, public.movies.imdbid"
" Index Cond: (public.movies.movieid = akatitles.movieid)"<br />
SELECT * FROM (
(SELECT DISTINCT title, movieid, year
FROM movies
WHERE title ILIKE '%Babe%' AND NOT (title ILIKE '"%}'))
UNION
(SELECT movies.title, movies.movieid, movies.year
FROM movies
INNER JOIN akatitles ON movies.movieid=akatitles.movieid
WHERE akatitles.title ILIKE '%Babe%' AND NOT (akatitles.title ILIKE '"%}'))
) AS union_tmp2;
Returns 612 Rows in 9078ms<br />
Database backup (plain text) is 1.61GB
这是一个非常复杂的查询,我对此并不完全了解,就像我说它是由JMDB吐出来的。
您对如何提高速度有什么建议吗?
答案 0 :(得分:3)
这是你的问题:
" -> Seq Scan on movies (cost=0.00..39093.65 rows=70 width=46)"
" Output: public.movies.title, public.movies.movieid, public.movies.year"
" Filter: (((title)::text ~~* '%Babe%'::text) AND ((title)::text !~~* '""%}'::text))"
顺序扫描和巨额成本,因为数据库无法在'%Babe%'上使用任何索引。看一下全文搜索,你可以创建一个合适的索引并让查询计划器使用它。
答案 1 :(得分:2)
使用双端外卡的查询(例如'%Babe%')无法利用任何索引,因此该表将导致顺序扫描而不是索引扫描。
如果您正在搜索'Babe%',那么您的索引应该有效。