Hello,
I have an SQL query which fetches the requested data from the database, but is using too much resources when doing so.

I would be happy to get advice on how to think / what to look for when trying to optimize a query, views, adding indexes, optimizing schema design and so on.

So far I've figured out that I could add appropriate indexes since the 'explain query plan' indicates the query is using many automatic indices, but I haven't added any extra yet since I would like to provide you with the original schema.

I'm not allowed to send the real database, but I've created a way to recreate the schema layout & add needed test data below. I'm sorry it's quite long, but since I'm not sure what optimizations might be done I rather describe too much than too little (but I've stripped some tables of columns I find irrelevant for the query in question).

I've also created an extra view 'query_view' which contains the query I'm trying to optimize. In the real application the 'v4.t1_searchvalue = 16' in the query_view is changing from time to time and not a static value.

SELECT v2_id FROM query_view;
Should result in v2_id's in order: 1, 4, 6, 8, 11, 3

I'm using SQLite 3.8.1

I would be very happy if you help me with the optimization, but even happier if you explain how you think to reach the goal.

It's also possible to tweak the database/view layout, but it depends on how big impact it would make to the processing speed.

Best regards,
Daniel



PRAGMA FOREIGN_KEYS = 0;

DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;
DROP TABLE IF EXISTS t3;
DROP TABLE IF EXISTS t4;
DROP TABLE IF EXISTS t5;
DROP TABLE IF EXISTS t6;

DROP TABLE IF EXISTS t7;
DROP TABLE IF EXISTS t8;
DROP TABLE IF EXISTS t9;
DROP TABLE IF EXISTS t10;
DROP TABLE IF EXISTS t11;
DROP TABLE IF EXISTS t12;
DROP TABLE IF EXISTS t13;
DROP TABLE IF EXISTS t14;
DROP TABLE IF EXISTS t15;
DROP TABLE IF EXISTS t16;

DROP VIEW IF EXISTS v1;
DROP VIEW IF EXISTS v2;
DROP VIEW IF EXISTS v3;
DROP VIEW IF EXISTS v4;

PRAGMA FOREIGN_KEYS = 1;

CREATE TABLE t1 (
    id INTEGER PRIMARY KEY,
    t1_searchvalue INT
);

CREATE TABLE t2 (
    id INTEGER PRIMARY KEY,
    t2_searchvalue INTEGER NOT NULL,
    t1_id INT NOT NULL,
CONSTRAINT "FK_t2" FOREIGN KEY( t1_id ) REFERENCES t1 ( id ) ON DELETE CASCADE
);

CREATE TABLE t3 (
    id INT NOT NULL,
    t3_value_1 varchar( 10 ) NOT NULL,
    disabled BOOLEAN,
    t3_value_2 BOOLEAN,
    CONSTRAINT "PK_t3" PRIMARY KEY(id)
);

CREATE TABLE t4 (
    id INTEGER PRIMARY KEY,
    t3_id INT NOT NULL,
    t4_value_1 VARCHAR( 10 ) NOT NULL,
    searchvalue INT NOT NULL,
    t2_id INT NOT NULL,

    CONSTRAINT "FK_t4_002" FOREIGN KEY( t3_id ) REFERENCES t3 ( id ),
CONSTRAINT "FK_t4_003" FOREIGN KEY( t2_id ) REFERENCES t2 ( id ) ON DELETE CASCADE
);

CREATE TABLE t5 (
    id INTEGER PRIMARY KEY,
    name VARCHAR(20) NOT NULL
);

CREATE TABLE t6 (
    id INTEGER PRIMARY KEY,
    starttime DATETIME NOT NULL,
    t5_id INT NOT NULL,
    t6_value_1 BOOLEAN NOT NULL,
    t6_value_2 BOOLEAN NOT NULL DEFAULT 0,

    CONSTRAINT 'FK_t6_001' FOREIGN KEY( t5_id ) REFERENCES t5 ( id )
);

CREATE TABLE t7 (
    key_part_1 INT NOT NULL,
    key_part_2 INT NOT NULL,
    last_seen DATETIME NOT NULL,
    t1_searchvalue INT NOT NULL,
    t2_searchvalue INT NOT NULL,
    t4_searchvalue INT NOT NULL,
    CONSTRAINT "PK_t7" PRIMARY KEY(key_part_1, key_part_2)
);

CREATE TABLE t8 (
    t6_id INT NOT NULL,
    t7_key_part_1 INT NOT NULL,
    t7_key_part_2 INT NOT NULL,
CONSTRAINT "FK_t8_001" FOREIGN KEY( t6_id ) REFERENCES t6 ( id ) ON DELETE CASCADE, CONSTRAINT "FK_t8_002" FOREIGN KEY(t7_key_part_1, t7_key_part_2) REFERENCES t7 ( key_part_1, key_part_2)
);

CREATE TABLE t9 (
    id INTEGER PRIMARY KEY,
    name VARCHAR(30),
    enabled BOOLEAN NOT NULL
);

CREATE TABLE t10 (
    t4_id INT NOT NULL,
    t9_id INT NOT NULL,
    CONSTRAINT 'PK_t10' PRIMARY KEY( t4_id, t9_id),
CONSTRAINT 'FK_t10_001' FOREIGN KEY( t4_id ) REFERENCES t4 ( id ) ON DELETE CASCADE, CONSTRAINT 'FK_t10_002' FOREIGN KEY( t9_id ) REFERENCES t9 ( id ) ON DELETE CASCADE
);

CREATE TABLE t11 (
    t3_id INT NOT NULL,
    t9_id INT NOT NULL,
    CONSTRAINT 'PK_t11' PRIMARY KEY( t3_id, t9_id),
CONSTRAINT 'FK_t11_001' FOREIGN KEY( t3_id ) REFERENCES t3 ( id ) ON DELETE CASCADE, CONSTRAINT 'FK_t11_002' FOREIGN KEY( t9_id ) REFERENCES t9 ( id ) ON DELETE CASCADE
);

CREATE TABLE t12 (
    t9_id INT NOT NULL,
    t3_id INT NOT NULL,
    CONSTRAINT 'PK_t12' PRIMARY KEY( t9_id, t3_id),
CONSTRAINT 'FK_t12_001' FOREIGN KEY( t9_id ) REFERENCES t9 ( id ) ON DELETE CASCADE, CONSTRAINT 'FK_t12_002' FOREIGN KEY( t3_id ) REFERENCES t3 ( id ) ON DELETE CASCADE
);

CREATE TABLE t13 (
    t9_id INT NOT NULL,
    day INT NOT NULL,
    starttime TIME NOT NULL,
    endtime TIME NOT NULL,
    CONSTRAINT 'PK_t13' PRIMARY KEY( t9_id, starttime, day),
CONSTRAINT 'FK_t13' FOREIGN KEY( t9_id ) REFERENCES t9 ( id ) ON DELETE CASCADE
);

CREATE TABLE t14 (
    t9_id INT NOT NULL,
    t5_id INT NOT NULL,
    CONSTRAINT 'PK_t14' PRIMARY KEY( t9_id, t5_id ),
CONSTRAINT 'FK_t14_001' FOREIGN KEY( t9_id) REFERENCES t9 ( id ) ON DELETE CASCADE, CONSTRAINT 'FK_t14_002' FOREIGN KEY( t5_id ) REFERENCES t5 ( id ) ON DELETE CASCADE
);

CREATE TABLE t15 (
    t6_id INT NOT NULL,
    t4_id INT NOT NULL,
CONSTRAINT "FK_t15_001" FOREIGN KEY( t6_id ) REFERENCES t6 ( id ) ON DELETE CASCADE,
    CONSTRAINT "FK_t15_001" FOREIGN KEY( t4_id ) REFERENCES t4 ( id )
);

CREATE TABLE t16(
    t5_id INT NOT NULL,
    t16_value_1 INT NOT NULL,
    priority INT NOT NULL,
    t16_value_2 INT NOT NULL,
    t16_value_3 INT NOT NULL,
    t16_value_4 INT NOT NULL,
    t16_value_5 INT NOT NULL,
    t16_value_6 INT NOT NULL,
    t16_value_7 INT NOT NULL,
    t16_value_8 INT NOT NULL,
    t16_value_9 INT NOT NULL,
    t16_value_10 INT NOT NULL,
    t16_value_11 INT NOT NULL
);

CREATE VIEW v1 AS
    SELECT     t6.id,
            t4.t3_id,
            t5_id,
            t6_value_1,
            t5.name AS t5_name,
            t4.id AS t4_id,
            starttime,
            t6.t6_value_2
    FROM t6, t15, t4, t5
    WHERE t6.id = t15.t6_id
    AND t15.t4_id = t4.id
    AND t6.t5_id = t5.id
    UNION
    SELECT    t6.id,
            t4.t3_id,
            t5_id,
            t6_value_1,
            t5.name AS t5_name,
            t4.id AS t4_id,
            starttime,
            t6.t6_value_2
    FROM t6, t8, t7, t4, t2, t1, t5
    WHERE t6.id = t8.t6_id
    AND t8.t7_key_part_1 = t7.key_part_1
    AND t6.t5_id = t5.id
    AND t4.t2_id = t2.id
    AND t2.t1_id = t1.id
    AND t7.t1_searchvalue = t1.t1_searchvalue
    AND t7.t2_searchvalue = t2.t2_searchvalue
    AND t7.t4_searchvalue = t4.searchvalue;

CREATE VIEW v2 AS
    SELECT  id,
            t3_id,
            v1.t5_id,
            t6_value_1,
            t5_name,
            t4_id,
            starttime,
            priority,
            t16_value_6,
            t16_value_7,
            t16_value_2,
            t16_value_5,
            t16_value_1,
            t16_value_3,
            t16_value_4,
            t16_value_8,
            t16_value_9,
            t16_value_11,
            v1.t6_value_2,
            t16_value_10
    FROM v1, t16
    WHERE v1.t5_id = t16.t5_id;


CREATE VIEW v3 AS
    SELECT DISTINCT t4_id, t3_id, t9_id
    FROM (    SELECT     t4.id AS t4_id,
                    t12.t3_id AS t3_id,
                    t9.id AS t9_id
            FROM t4, t10, t9, t12
            WHERE t4.id= t10.t4_id
            AND    t10.t9_id = t9.id
            AND t9.id = t12.t9_id
            AND t9.enabled = 1
            UNION
            SELECT     t4.id AS t4_id,
                    t12.t3_id,
                    t9.id AS t9_id
            FROM t4, t3, t11, t9, t12
            WHERE t4.t3_id = t3.id
            AND t3.id = t11.t3_id
            AND t11.t9_id = t9.id
            AND t9.id = t12.t9_id
            AND t9.enabled = 1 )
    WHERE t9_id IN (SELECT id
                    FROM t9
                    WHERE id NOT IN (SELECT t9_id FROM t13)
                    UNION
                    SELECT id
                    FROM t9, t13
                    WHERE t9.id = t13.t9_id
                    AND t13.day = strftime('%w', 'now', 'localtime')
AND t13.starttime <= strftime('%H:%M', 'now', 'localtime')
                    AND t13.endtime > strftime('%H:%M', 'now', 'localtime')
    )
    AND t3_id NOT IN (SELECT id FROM t3 WHERE disabled = 1);

CREATE VIEW v4 AS
    SELECT t4.id AS t4_id,
    t1.id AS t1_id,
    t2.id AS t2_id,
    t1.t1_searchvalue,
    t2.t2_searchvalue,
    t4.searchvalue
    FROM t1, t2, t4
    WHERE t1.id = t2.t1_id
    AND t2.id = t4.t2_id;

--create testdata
pragma recursive_triggers = 1;

CREATE TRIGGER ins_trigger_1 after insert on t3
  when new.id < 32
BEGIN
    INSERT INTO t3 VALUES(new.id+1, new.t3_value_1, 0, 0);
END;

CREATE TRIGGER ins_trigger_2 after insert on t1
BEGIN
    INSERT INTO t2 VALUES(NULL, 1 , new.id);
    INSERT INTO t2 VALUES(NULL, 2 , new.id);
    INSERT INTO t2 VALUES(NULL, 3 , new.id);
END;

CREATE TRIGGER ins_trigger_3 after insert on t2
BEGIN
    INSERT INTO t4 VALUES(NULL,new.t1_id,'text',0,new.id);
END;

CREATE TRIGGER ins_trigger_4 after insert on t4
  when new.searchvalue < 29
BEGIN
INSERT INTO t4 VALUES(NULL,new.t3_id,'text',new.searchvalue+1,new.t2_id);
END;

CREATE TRIGGER ins_trigger_5 after insert on t1
 WHEN NEW.t1_searchvalue < 16
 BEGIN
    INSERT INTO t1 VALUES(NULL, new.t1_searchvalue+1);
END;

CREATE TRIGGER ins_trigger_6 after insert on t5
 WHEN NEW.id < 32
 BEGIN
    INSERT INTO t5 VALUES(NULL, 'text');
END;

CREATE TRIGGER ins_trigger_7 after insert on t7
 WHEN NEW.key_part_1 < 1000
 BEGIN
    INSERT INTO t7 VALUES(new.key_part_1+1, 1, datetime(), 1, 1, 1);
END;

CREATE TRIGGER ins_trigger_8 after insert on t16
 WHEN NEW.t5_id < 32
 BEGIN
INSERT INTO t16 VALUES(new.t5_id+1, 1, new.t5_id+1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0);
END;

INSERT INTO t3 VALUES(1, 'text', 0, 0);
INSERT INTO t5 VALUES(1, 'text');
INSERT INTO t1 VALUES(NULL, 1);
INSERT INTO t7 VALUES(1, 1, datetime(), 1, 1, 1);
INSERT INTO t16 VALUES(1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0);

pragma recursive_triggers = 0;

DROP TRIGGER IF EXISTS ins_trigger_1;
DROP TRIGGER IF EXISTS ins_trigger_2;
DROP TRIGGER IF EXISTS ins_trigger_3;
DROP TRIGGER IF EXISTS ins_trigger_4;
DROP TRIGGER IF EXISTS ins_trigger_5;
DROP TRIGGER IF EXISTS ins_trigger_6;
DROP TRIGGER IF EXISTS ins_trigger_7;
DROP TRIGGER IF EXISTS ins_trigger_8;

INSERT INTO t9 VALUES(1, 'conn 1 (enabled)', 1);
INSERT INTO t14 VALUES(1, 2);
INSERT INTO t9 VALUES(2, 'conn 2 (disabled)', 0);
INSERT INTO t14 VALUES(2, 2);
INSERT INTO t9 VALUES(3, 'conn 3 (inside constraint)', 1);
INSERT INTO t14 VALUES(3, 2);
INSERT INTO t13 VALUES(3, 0, '00:00', '23:59');
INSERT INTO t13 VALUES(3, 1, '00:00', '23:59');
INSERT INTO t13 VALUES(3, 2, '00:00', '23:59');
INSERT INTO t13 VALUES(3, 3, '00:00', '23:59');
INSERT INTO t13 VALUES(3, 4, '00:00', '23:59');
INSERT INTO t13 VALUES(3, 5, '00:00', '23:59');
INSERT INTO t13 VALUES(3, 6, '00:00', '23:59');

INSERT INTO t9 VALUES(4, 'conn 4 (outside constraint)', 1);
INSERT INTO t14 VALUES(4, 2);
INSERT INTO t13 VALUES(4, 0, '04:00', '04:01');

INSERT INTO t12 VALUES(1, 15);
INSERT INTO t12 VALUES(2, 14);
INSERT INTO t12 VALUES(3, 13);
INSERT INTO t12 VALUES(4, 12);

INSERT INTO t11 VALUES(16, 1);
INSERT INTO t11 VALUES(16, 2);
INSERT INTO t11 VALUES(16, 3);
INSERT INTO t11 VALUES(16, 4);

INSERT INTO t9 VALUES(5, 'conn 4 (added to node)', 1);
INSERT INTO t12 VALUES(5, 11);
INSERT INTO t14 VALUES(5, 2);
INSERT INTO t10 VALUES(1, 5);

INSERT INTO t6 VALUES(1, '2013-11-05 14:47:02', 2, 0, 0);
INSERT INTO t15 VALUES(1, 1);

INSERT INTO t6 VALUES(2, '2013-11-05 14:47:02', 3, 0, 0);
INSERT INTO t15 VALUES(2, 2);

UPDATE t16 SET priority = 2 WHERE t5_id = 4;
INSERT INTO t6 VALUES(3, '2013-11-05 14:47:02', 4, 0, 0);
INSERT INTO t15 VALUES(3, 2);

INSERT INTO t6 VALUES(4, '2013-11-05 14:48:02', 2, 0, 0);
INSERT INTO t8 VALUES(4, 1, 1);
UPDATE t7 SET t1_searchvalue = 16 where key_part_1 = 1;

INSERT INTO t6 VALUES(5, '2013-11-05 14:48:02', 5, 0, 0);
INSERT INTO t8 VALUES(5, 1, 1);

INSERT INTO t6 VALUES(6, '2013-11-05 14:47:02', 2, 0, 0);
INSERT INTO t15 VALUES(6, 91);

INSERT INTO t6 VALUES(7, '2013-11-05 14:47:02', 2, 0, 0);
INSERT INTO t15 VALUES(7, 181);

INSERT INTO t6 VALUES(8, '2013-11-05 14:47:02', 2, 0, 0);
INSERT INTO t15 VALUES(8, 271);

INSERT INTO t6 VALUES(9, '2013-11-05 14:47:02', 2, 0, 0);
INSERT INTO t15 VALUES(9, 361);

UPDATE t16 SET priority = 2 WHERE t5_id = 6;
INSERT INTO t6 VALUES(10, '2013-11-05 14:47:02', 6, 0, 0);
INSERT INTO t15 VALUES(10, 361);

INSERT INTO t6 VALUES(11, '2013-11-05 14:47:02', 2, 0, 0);
INSERT INTO t15 VALUES(11, 451);

INSERT INTO t6 VALUES(12, '2013-11-05 14:47:02', 1, 0, 0);
INSERT INTO t15 VALUES(12, 541);

INSERT INTO t6 VALUES(13, '2013-11-05 14:47:02', 2, 0, 0);
INSERT INTO t15 VALUES(13, 541);


CREATE VIEW query_view AS
SELECT    temp_table.v2_id,
        temp_table.t4_value_1,
        temp_table.t3_id,
        v4.t2_searchvalue AS t2_searchvalue,
        v4.searchvalue AS t4_searchvalue,
        t16_value_1,
        t16_value_2,
        temp_table.priority AS priority,
strftime('%s', datetime('now'), 'localtime') - strftime('%s', temp_table.starttime) AS timer,
        t3_value_2,
        t6_value_1,
        t3.t3_value_1,
        t16_value_3,
        t16_value_4,
        t16_value_9,
        t16_value_8,
        t16_value_10,
        t6_value_2,
        (t5.id>=1000 AND t5.id<2000) as is_special_type

FROM     v4,

(SELECT v2.id AS v2_id, v2.t3_id, priority, t5_id, t6_value_1, t4.t4_value_1, t16_value_1, t16_value_2, t16_value_3, t16_value_4, t16_value_9, t16_value_8, t6_value_2, t16_value_10, starttime, t4.id AS t4_id
         FROM v2, t4
         WHERE v2.t4_id = t4.id ) AS temp_table,

        (SELECT t3_id, min(priority) AS priority
         FROM v1, t16
         WHERE v1.t5_id = t16.t5_id
         GROUP BY t3_id) AS mintable,

         t5,
         t3

WHERE temp_table.t3_id = mintable.t3_id
AND temp_table.priority = mintable.priority
AND t5.id = temp_table.t5_id
AND t3.id = temp_table.t3_id
AND v4.t4_id = temp_table.t4_id
AND temp_table.v2_id IN (SELECT v1.id
                            FROM v1, v3, v4
                            WHERE v1.t3_id = v3.t3_id
                            AND v1.t5_id IN (SELECT t5_id
                                             FROM t14
                                             WHERE t14.t9_id = v3.t9_id)
                            AND v3.t4_id = v4.t4_id
                            AND v4.t1_searchvalue = 16
                            UNION
                            SELECT v1.id AS v1_id
                            FROM v1, v4, t4
                            WHERE v1.t3_id = t4.t3_id
                            AND t4.id = v4.t4_id
                            AND v4.t1_searchvalue = 16 )
ORDER BY priority, t5_id
LIMIT 20;





_______________________________________________
sqlite-users mailing list
[email protected]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to