【问题标题】:SQLite index performanceSQLite 索引性能
【发布时间】:2018-06-12 22:35:47
【问题描述】:

我有一个如下布局的表格

email, item_id, json 在哪里

  • email 是一个字符串
  • item_id 是以毫秒为单位的 unix 时间戳
  • json 是要与 JSON1 扩展一起使用的项目数据

我在该表上也有一个多列索引,email, id

我以WHERE email = 'asd' AND item_id > ... AND item_id < ...的样式执行了很多查询

我已经和MongoDB打交道太多年了,所以我习惯了不处理数据库规范化,而只是使用最简单的SQL表布局。

在手机上,对于 35000 个项目的查询,对上述样式的查询最多可能需要一秒钟。索引确实被使用了。

当我通过使用email, email_id 创建一个新表并将原始表更改为email_id, item_id, json 并开始通过JOINS 查询来规范化数据库时,我是否会获得显着的性能提升?在这种情况下,email, email_id 将包含大约 2-5 个项目,email_id, item_id, json 将包含数千个。

【问题讨论】:

    标签: performance sqlite indexing


    【解决方案1】:

    使用 3 测试原始,一个使用 JOIN 的查询和一个附加选项,使用子查询而不是连接来根据电子邮件地址获取电子邮件 ID,并将其与 email_id 进行比较。子查询名列前茅,原来的表现最差。

    结果是:-

    SELECT * FROM original WHERE email = 'email3@ouremail.com' AND item_id > 7800 AND item_id < 2404327029516376406
    

    好的 时间:0.199s

    SELECT * FROM item WHERE email_id = (SELECT email.email_id FROM email WHERE email.email = 'email3@ouremail.com') AND item_id > 7800 AND item_id < 2404327029516376406
    

    好的 时间:0.082s

    SELECT * FROM item JOIN email ON item.email_id = email.email_id WHERE email.email = 'email3@ouremail.com' AND item_id > 7800 AND item_id < 2404327029516376406
    

    好的 时间:0.109s

    以下用于创建和测试:-

    DROP TABLE IF EXISTS original;
    CREATE TABLE IF NOT EXISTS original (email TEXT, item_id INTEGER, json BLOB, PRIMARY KEY(email,item_id));
    WITH RECURSIVE cnt(x,y,z) 
    AS (
        SELECT 'email'||(1 + ABS(random() / (9223372036854775807 / 5)))||'@ouremail.com',
                    ABS(random()),
              randomblob(ABS(random() / (9223372036854775807 / 40) ))
                UNION ALL SELECT 
                  'email'||(1 + ABS(random() / (9223372036854775807 / 5)))||'@ouremail.com',
                    ABS(random()),
                    randomblob(ABS(random() / (9223372036854775807 / 40)))  
                FROM cnt LIMIT 350000
    )
    INSERT INTO original SELECT * FROM cnt;
    
    
    DROP TABLE IF EXISTS email;
    CREATE TABLE IF NOT EXISTS email (email_id INTEGER PRIMARY KEY, email TEXT);
    INSERT INTO email SELECT DISTINCT null,email FROM original;
    
    
    DROP TABLE IF EXISTS item;
    CREATE TABLE IF NOT EXISTS item (email_id, item_id, json);
    INSERT INTO item SELECT 
        (SELECT email_id FROM email WHERE original.email = email.email),
            item_id,
            json FROM original;
    
    
    SELECT * FROM original WHERE email = 'email3@ouremail.com' AND item_id > 7800 AND item_id < 2404327029516376406;
    SELECT * FROM item WHERE email_id = (SELECT email.email_id FROM email WHERE email.email = 'email3@ouremail.com') AND item_id > 7800 AND item_id < 2404327029516376406; 
    SELECT * FROM item JOIN email ON item.email_id = email.email_id WHERE email.email = 'email3@ouremail.com' AND item_id > 7800 AND item_id < 2404327029516376406;
    

    您可能会更糟糕的是运行以下命令并查看输出。

    EXPLAIN QUERY PLAN SELECT * FROM original WHERE email = 'email3@ouremail.com' AND item_id > 7800 AND item_id < 2404327029516376406;
    EXPLAIN QUERY PLAN SELECT * FROM item WHERE email_id = (SELECT email.email_id FROM email WHERE email.email = 'email3@ouremail.com') AND item_id > 7800 AND item_id < 2404327029516376406;
    EXPLAIN QUERY PLAN SELECT * FROM item JOIN email ON item.email_id = email.email_id WHERE email.email = 'email3@ouremail.com' AND item_id > 7800 AND item_id < 2404327029516376406;
    

    【讨论】:

    • 感谢您展示如何仅使用 SQL 创建这样的基准。
    猜你喜欢
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 2012-02-29
    • 2022-11-04
    • 2016-05-01
    • 2017-08-29
    • 2010-10-29
    • 1970-01-01
    相关资源
    最近更新 更多