WebSQL 查询优化帮助 - CASE WHEN 使查询慢 400 毫秒
Posted
技术标签:
【中文标题】WebSQL 查询优化帮助 - CASE WHEN 使查询慢 400 毫秒【英文标题】:WebSQL query optimization help - CASE WHEN makes query 400 ms slow 【发布时间】:2012-10-23 12:06:59 【问题描述】:有人可以告诉我为什么“CASE WHEN”会变得如此缓慢以及如何优化/修复它吗?
需要将被固定的项目按顺序排列在结果的首位。
我可能可以在 sql 查询之后执行此操作,但我认为如果操作正确,如果在 sql 查询内完成此排序会更快。
慢查询~490ms
SELECT
places.id AS place_id,
url,
title,
thumbnails.score AS score,
thumbnails.clipping AS clipping,
thumbnails.lastModified AS lastModified,
EXISTS (SELECT 1 FROM pinned pi WHERE pi.place_id = places.id) AS pinned
FROM places
LEFT JOIN thumbnails ON (thumbnails.place_id = places.id)
LEFT JOIN pinned j ON (j.place_id = places.id) WHERE (hidden == 0)
ORDER BY case when j.id is null then 1 else 0 end,
j.id,
frecency DESC LIMIT 24
删除“CASE WHEN”部分: 查询~6ms
SELECT
places.id AS place_id,
url,
title,
thumbnails.score AS score,
thumbnails.clipping AS clipping,
thumbnails.lastModified AS lastModified,
EXISTS (SELECT 1 FROM pinned pi WHERE pi.place_id = places.id) AS pinned
FROM places
LEFT JOIN thumbnails ON (thumbnails.place_id = places.id) WHERE (hidden == 0)
ORDER BY frecency DESC LIMIT 24
表信息:
var Create_Table_Places =
'CREATE TABLE places (' +
'id INTEGER PRIMARY KEY,' +
'url LONGVARCHAR,' +
'title LONGVARCHAR,' +
'visit_count INTEGER DEFAULT 0,' +
'hidden INTEGER DEFAULT 0 NOT NULL,' +
'typed INTEGER DEFAULT 0 NOT NULL,' +
'frecency INTEGER DEFAULT -1 NOT NULL,' +
'last_visit_date INTEGER,' +
'dateAdded INTEGER,' +
'lastModified INTEGER' +
')';
var Create_Table_Thumbnails =
'CREATE TABLE thumbnails (' +
'id INTEGER PRIMARY KEY,' +
'place_id INTEGER UNIQUE,' +
'data LONGVARCHAR,' +
'score REAL,' +
'clipping INTEGER,' +
'dateAdded INTEGER,' +
'lastModified INTEGER' +
')';
var Create_Table_Pinned =
'CREATE TABLE pinned (' +
'id INTEGER PRIMARY KEY,' +
'place_id INTEGER UNIQUE,' +
'position INTEGER,' +
'dateAdded INTEGER,' +
'lastModified INTEGER' +
')';
【问题讨论】:
Sql 优化器可以是一个善变的情妇。我建议阅读这篇文章,然后重新访问您的查询,看看是否有任何见解打动了您。 sommarskog.se/query-plan-mysteries.html 【参考方案1】:要了解查询执行是否存在根本差异,请使用EXPLAIN QUERY PLAN
。
在 SQLite 3.7.almost15 中,您的查询有以下计划:
selectid order from detail
-------- ----- ---- ------
0 0 0 SCAN TABLE places (~100000 rows)
0 1 1 SEARCH TABLE thumbnails USING INDEX sqlite_autoindex_thumbnails_1 (place_id=?) (~1 rows)
0 2 2 SEARCH TABLE pinned AS j USING COVERING INDEX sqlite_autoindex_pinned_1 (place_id=?) (~1 rows)
0 0 0 EXECUTE CORRELATED SCALAR SUBQUERY 1
1 0 0 SEARCH TABLE pinned AS pi USING COVERING INDEX sqlite_autoindex_pinned_1 (place_id=?) (~1 rows)
0 0 0 USE TEMP B-TREE FOR ORDER BY
selectid order from detail
-------- ----- ---- ------
0 0 0 SCAN TABLE places (~100000 rows)
0 1 1 SEARCH TABLE thumbnails USING INDEX sqlite_autoindex_thumbnails_1 (place_id=?) (~1 rows)
0 0 0 EXECUTE CORRELATED SCALAR SUBQUERY 1
1 0 0 SEARCH TABLE pinned AS pi USING COVERING INDEX sqlite_autoindex_pinned_1 (place_id=?) (~1 rows)
0 0 0 USE TEMP B-TREE FOR ORDER BY
这两个计划几乎相同,除了重复的pinned
查找。
如果您的 SQLite 不以这种方式执行查询,请更新它。
在您的第一个查询中,您可以删除pinned
字段的子查询,因为您已经加入了pinned
表,并且您正在执行与为连接完成的查找完全相同的查找;请改用j.id IS NOT NULL
。
您的CASE WHEN
的目的是将NULL
s 排序在其他值之后。
你可以通过converting all NULL
s对某个值为sorted after numbers的值来达到同样的效果,比如一个字符串:
... ORDER BY IFNULL(j.id, ''), frecency DESC
但是,理论上,这与 CASE WHEN
的运行时差异应该不大。
【讨论】:
以上是关于WebSQL 查询优化帮助 - CASE WHEN 使查询慢 400 毫秒的主要内容,如果未能解决你的问题,请参考以下文章
SQL 逻辑优化 case when 转为 union all
SQL查询语句SELECT中带有case when嵌套子查询判断的问题
这两个case when end的条件语句查询结果为啥不一致