【问题标题】:WebSQL query optimization help - CASE WHEN makes query 400 ms slowWebSQL 查询优化帮助 - CASE WHEN 使查询慢 400 毫秒
【发布时间】: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' +
    ')';

【问题讨论】:

标签: sqlite query-optimization


【解决方案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 的目的是将NULLs 排序在其他值之后。 你可以通过converting all NULLs对某个值为sorted after numbers的值来达到同样的效果,比如一个字符串:

... ORDER BY IFNULL(j.id, ''), frecency DESC

但是,理论上,这与 CASE WHEN 的运行时差异应该不大。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-15
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    • 2014-02-06
    • 2011-05-06
    • 2011-03-01
    • 1970-01-01
    相关资源
    最近更新 更多