【问题标题】:Sqlite Query Optimization (select * from where in AND not in order by limit offset)Sqlite 查询优化(select * from where in AND not in order by limit offset)
【发布时间】:2010-02-17 05:22:48
【问题描述】:

对于使用 Sqlite3 优化以下查询有什么想法吗?

SELECT * FROM Feed 
    WHERE ActivityType IN ('PhotoActivity','CommentActivity') 
    AND UserKey NOT IN ('testUser', 'testUser2') 
    ORDER BY TimeStamp DESC 
    LIMIT 20 OFFSET 0;

该表的记录永远不会超过 100,000 条,我们预计会进行 100 到 1 次读取和写入。

非常感谢任何帮助。

表Sql是:

CREATE TABLE Feed (
        FeedActivityKey TEXT PRIMARY KEY,           
        UserKey TEXT,
        AssemblyQualifiedName TEXT,
        SerializedObject BLOB,
        ActivityType TEXT,
        CorrelatedKey TEXT,
        TimeStamp INTEGER);
    CREATE INDEX Feed_ActivityTypeUserKey ON [FriendFeed] (
    [ActivityType], [UserKey] DESC);
    CREATE INDEX Feed_UserKey ON [FriendFeed] (
    [UserKey] DESC);
    CREATE INDEX Feed_TimeStamp ON [FriendFeed] (
    [TimeStamp] DESC);

解释输出是:

0 轨迹 0 0 0 0

1 OpenEphemeral 1 3 0 keyinfo(1,-BINARY) 0

2 整数 20 1 0 0

3 MustBeInt 1 0 0 0

4 如果零 1 73 0 0

5 整数 0 2 0 0

6 MustBeInt 2 0 0 0

7 IfPos 2 9 0 0

8 整数 0 2 0 0

9 加 1 2 3 0

10个IfPos 1 12 0 0

11 整数 -1 3 0 0

12 String8 0 4 0 PhotoActivity 0

13 String8 0 5 0 评论活动 0

14 转到 0 74 0 0

15 打开读取 0 2 0 7 0

16 OpenRead 2 4 0 keyinfo(2,BINARY,BINARY) 0

17 如果 7 25 0 0

18 整数 1 7 0 0

19 OpenEphemeral 4 1 0 keyinfo(1,BINARY) 0

20 空 0 9 0 0

21 制作记录 4 1 9 a 0

22 IdxInsert 4 9 0 0

23 制作记录 5 1 9 a 0

24 IdxInsert 4 9 0 0

25 倒带 4 53 0 0

26 列 4 0 6 0

27 IsNull 6 52 0 0

28 亲和力 6 1 0 aab 0

29 寻格 2 52 6 1 0

30 IdxGE 2 52 6 1 1

31 IdxRowid 2 9 0 0

32 寻找 0 9 0 0

33 列 0 0 10 0

34 列 2 1 11 0

35 列 0 2 12 0

36 列 0 3 13 0

37 列 2 0 14 0

38 列 0 5 15 0

39 列 0 6 16 0

40 制作记录 10 7 9 0

41 列 0 6 17 0

42 序列 1 18 0 0

43 移动 9 19 1 0

44 制作记录 17 3 8 0

45 IdxInsert 1 8 0 0

46 如果零 3 49 0 0

47 AddImm 3 -1 0 0

48 转到 0 51 0 0

49 最后 1 0 0 0

50 删除 1 0 0 0

51 下一个 2 30 0 0

52 下一个 4 26 0 0

53 关闭 0 0 0 0

54 关闭 2 0 0 0

55 开放伪 5 1 7 0

56 排序 1 72 0 0

57 AddImm 2 -1 0 0

58 IfNeg 2 60 0 0

59 转到 0 71 0 0

60 列 1 2 9 0

61 整数 1 8 0 0

62 插入 5 9 8 0

63 列 5 0 10 0

64 列 5 1 11 0

65 列 5 2 12 0

66 列 5 3 13 0

67 列 5 4 14 0

68 列 5 5 15 0

69 列 5 6 16 0

70 结果行 10 7 0 0

71 下一个 1 57 0 0

72 关闭 5 0 0 0

73 暂停 0 0 0 0

74 事务 0 0 0 0

75 验证Cookie 0 5 0 0

76 表锁 0 2 0 FriendFeed 0

77 转到 0 15 0 0

【问题讨论】:

  • 我认为这只是一个错字,但您提供的 DDL 创建了一个名为 Feed 的表,但索引了一个名为 FriendFeed 的表。如果情况确实如此,那么您并没有为您选择的表编制索引。
  • (ActivityType)、(UserKey)、(ActivityType, UserKey)的基数是多少?它们是否受到可以存储整数 ID 的参考表的支持?
  • 这些数据库将按用户存储在拥有大量用户的系统中。为这些存储参考表会导致大量重复数据。我可以为活动类型使用枚举,但在此数据集的上下文中,UserKey 可能是未知值。
  • 运行分析后,我设法将查询缩短到 8 毫秒。

标签: sqlite


【解决方案1】:
  • 将列添加到您的选择中
  • 进一步规范化表格。例如,您可以在具有数字主键的不同表中定义 ActivityType,UserKey
  • 由于您有 100 比 1 的读取到写入,请在选择之前发出 SHARED 锁定(如果必须,写入过程可以等待更长的时间)

【讨论】:

  • 我可能可以规范化 ActivityType 但由于我们应用程序的结构,UserKey 是不可能的。也许用户密钥的哈希码会比当前的实现更快?大多数用户键都是 GUIDS。
  • 查询需要多长时间?您是在桌面还是移动环境中发布问题?
  • 桌面环境。对于 100,000 行,查询需要 1019 毫秒
  • 好的。我认为您的问题是需要从磁盘传输到内存的数据量。尝试将 select * 限制为更精确的值。如果使用有限的返回列满足您的需求,并且您需要查询中的所有列,请尝试以 gzip 格式保存数据繁重的列,以减少从磁盘到内存的数据。
  • 该表有 100,000 条记录,但我只取前 20 条匹配的记录。
【解决方案2】:

我会删除 select * from 并将其更改为 select [column1], [column2] from

这样做的原因是您只返回您需要的值(即:我看到您的表有 6 列,但您的结果中只返回 5 列。),它减少了开销,因为您不使用通配符。

【讨论】:

    【解决方案3】:

    也许 OR 会比 IN 快?


    编辑 检查这个:http://www.sqlite.org/optoverview.html#or_opt

    【讨论】:

    • 不,不是。 IN 语法更快。 (仅解析一次)
    • 无论如何我都需要 AND 语法。我阅读了优化说明并为它们设置了索引...我不熟悉操作码,希望知道它们的人能提供帮助。跨度>
    猜你喜欢
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-05
    • 1970-01-01
    • 2011-11-24
    相关资源
    最近更新 更多