我的应用程序中有许多看起来像这样的查询;
SELECT DISTINCT STREET_NUMBER, STREET_NAME
FROM leads
WHERE STREET_NAME || ',' || SUBURB IN (select VAL from streetFilter)
AND USER_ID IN (%@)
AND TIMESTAMP >= '%@'
AND TIMESTAMP <= '%@'
AND GEO_LAT <> '0'
ORDER BY STREET_NAME, CAST(`STREET_NUMBER` AS SIGNED) ASC
我的问题是,我应该为哪些值或值集添加索引。
到目前为止,我刚刚添加了所有内容,即CREATE INDEX temp ON lead('见下文')
STREET_NUMBER
AS SIGNED))STREET_NUMBER
AS SIGNED))但我知道这不可能是正确的。 任何人都可以指出哪些不起作用或不会使我的查询更快,哪个会?
数据库是sqlite
我的创建声明: @“CREATE TABLE IF NOT EXISTS lead(LEAD_ID BIGINT PRIMARY KEY,USER_ID INTEGER,GEO_LAT,GEO_LONG,CUSTOMER_NAME,UNIT_NUMBER,STREET_NUMBER,STREET_NAME,SUBURB,STATE,POSTCODE INTEGER,NMI,DPI_MIRN,STATUS,STATUS_INT INTEGER,OUTCOME INTEGER,OUTCOME_FULL INTEGER ,FINAL_CODE INTEGER,NOTES,NOTES_EXTRA,TIMESTAMP)“];
719130; 50; -32.933871; 151.774978; David Lee先生; 1; 34; LEMNOS PDE; NEWCASTLE; NSW; 2300 ;;; P; 0; 0 ;; 0 ;; 0:0:0; 20120602174036 719233; 50; -32.9307183; 151.7803428; Mitch James先生; 1; 1-7; TYRRELL ST; THE HILL; NSW; 2300 ;;; P; 0; 0 ;; 0 ;; 0:0:0; 20120602174036 719234; 50; -32.933155; 151.777351; Ben Foster先生;; 4; BINGLE ST; NEWCASTLE; NSW; 2300; 41021027208; 52404368858; C; 0; 0 ;; 0 ;; 0:0:0; 20120602174036 719300; 50; -32.9291125; 151.785025; Marilyn Rajakulenthiran女士; U 12; 3; KING ST; NEWCASTLE; NSW; 2300 ;;; P; 0; 0 ;; 0 ;; 0:0:0; 20120602174036
查询现在是SELECT LEAD_ID,USER_ID,UNIT_NUMBER,STREET_NUMBER,STREET_NAME,SUBURB,STATE,POSTCODE,STATUS_INT,OUTCOME,CUSTOMER_NAME,NOTES FROM lead JOIN outcomeFilter ON leads.OUTCOME = outcomeFilter.VAL JOIN suburbFilter ON leads.SUBPOST = suburbFilter .VAL WHERE USER_ID IN(%@)和TIMESTAMP BETWEEN'%@'和'%@'ORDER BY SUBURB,STREET_NAME,CAST(STREET_NUMBER AS SIGNED)
我的初期仍然没有改善。似乎是通过减慢最多的顺序来订购
答案 0 :(得分:0)
最好的办法是查看查询执行计划并检查返回的建议索引。索引太多和/或在错误的位置实际上会损害性能,这会适得其反。
访问执行计划:
在“查询”菜单上,单击“显示执行计划”,然后运行查询 在查询窗口中。执行计划和查询结果现在显示在 窗口的单独窗格,以便您可以一起查看它们。
答案 1 :(得分:0)
你可以在表格的几乎所有字段上进行范围扫描。
我建议查看解释,然后看看以下内容是否更好:
create index lookup_idx on leads(user_id, timestamp, geo_lat).
如果您使用的是MySQL,则无法使用该索引的geo_lat部分,因此请使用(user_id,timestamp)。 Oracle可以在范围内执行SKIP SCANS,因此如果使用Oracle,请将geo_lat保留在索引中。
让我们确切地知道您正在使用哪个数据库并发布EXPLAIN PLAN(无论您是为该RDBMS获取它)还是发布导联的CREATE TABLE,以便我们可以看到发生了什么。
编辑注意到这是SQLlite。在这种情况下可能是(user_id,timestamp),但我可以稍后用SQLfiddle检查。
再次,请发布CREATE TABLE和一些示例数据。
答案 2 :(得分:0)
一般来说,您只需要在搜索,排序,加入或WHERE条件中涉及的字段上使用索引(可能)。您的表中有几个字段没有落入任何这些类别;可以安全地消除这些字段的索引,而不会对查询的性能产生负面影响。
运行执行计划将告诉您执行的字段的任何索引是否属于这些类别之一也是不必要的。例如,如果字段的基数如此之小(即,只有很少的唯一值),索引就无法帮助,这是可能的。
有关SQLite特定优化和索引使用的更多信息,请访问:http://www.sqlite.org/optoverview.html。
值得注意的是:SQLite最多只能为查询中的每个表使用一个索引。见Choosing between multiple indices。 ANALYZE命令将帮助您确定哪些索引最有价值。