How to emulate partial multicolumn (compozite) index in Oracle 11.2?
Big table
record (
id number primary key,
city_id number not null,
organization_id number not null,
department_id number not null, -- extra context, can be 0
renew_date date not null -- frequently updated
)
Two kind of query are used:
1.
WITH cte (city_id, organization_id, -- etc...) AS (
-- table join routine...
)
SELECT r.*
FROM record r
INNER JOIN cte t ON r.city_id = t.city_id AND r.organization_id = t.organization_id AND r.department_id = 0
WHERE -- some condition on renew_date... whatever
2.
WITH cte (city_id, organization_id, department_id, -- etc...) AS (
-- same
)
SELECT r.*
FROM record r
INNER JOIN cte t ON r.city_id = t.city_id AND r.organization_id = t.organization_id AND r.department_id = t.department_id
WHERE -- some condition on renew_date or smth else
There are rumors that partial multicolumn (compozite) index can be emulated in Oracle.
https://community.oracle.com/ideas/18213
https://blog.jooq.org/2017/01/18/how-to-emulate-partial-indexes-in-oracle/
Do i need to create a pair of some kind of hash function
CREATE OR REPLACE FUNCTION get_record_index (city_id IN NUMBER, organization_id IN NUMBER, department_id IN NUMBER)
RETURN NUMBER
DETERMINISTIC
AS
BEGIN
IF department_id <> 0 THEN RETURN NULL
ELSE RETURN no_idea_how_to_compute(city_id, organization_id);
END IF;
END;
CREATE OR REPLACE FUNCTION get_record_department_index (city_id IN NUMBER, organization_id IN NUMBER, department_id IN NUMBER)
RETURN NUMBER
DETERMINISTIC
AS
BEGIN
IF department_id = 0 THEN RETURN NULL
ELSE RETURN no_idea_how_to_compute2(city_id, organization_id, department_id);
END IF;
END;
and create two function based index?
upd:
I need smth like that
CREATE INDEX record_main_index ON record (rayon_id, organization_id) WHERE department_id = 0;
CREATE INDEX record_department_index ON record (rayon_id, organization_id, department_id) WHERE department_id <> 0;
oracle indexing plsql oracle11g
add a comment |
Big table
record (
id number primary key,
city_id number not null,
organization_id number not null,
department_id number not null, -- extra context, can be 0
renew_date date not null -- frequently updated
)
Two kind of query are used:
1.
WITH cte (city_id, organization_id, -- etc...) AS (
-- table join routine...
)
SELECT r.*
FROM record r
INNER JOIN cte t ON r.city_id = t.city_id AND r.organization_id = t.organization_id AND r.department_id = 0
WHERE -- some condition on renew_date... whatever
2.
WITH cte (city_id, organization_id, department_id, -- etc...) AS (
-- same
)
SELECT r.*
FROM record r
INNER JOIN cte t ON r.city_id = t.city_id AND r.organization_id = t.organization_id AND r.department_id = t.department_id
WHERE -- some condition on renew_date or smth else
There are rumors that partial multicolumn (compozite) index can be emulated in Oracle.
https://community.oracle.com/ideas/18213
https://blog.jooq.org/2017/01/18/how-to-emulate-partial-indexes-in-oracle/
Do i need to create a pair of some kind of hash function
CREATE OR REPLACE FUNCTION get_record_index (city_id IN NUMBER, organization_id IN NUMBER, department_id IN NUMBER)
RETURN NUMBER
DETERMINISTIC
AS
BEGIN
IF department_id <> 0 THEN RETURN NULL
ELSE RETURN no_idea_how_to_compute(city_id, organization_id);
END IF;
END;
CREATE OR REPLACE FUNCTION get_record_department_index (city_id IN NUMBER, organization_id IN NUMBER, department_id IN NUMBER)
RETURN NUMBER
DETERMINISTIC
AS
BEGIN
IF department_id = 0 THEN RETURN NULL
ELSE RETURN no_idea_how_to_compute2(city_id, organization_id, department_id);
END IF;
END;
and create two function based index?
upd:
I need smth like that
CREATE INDEX record_main_index ON record (rayon_id, organization_id) WHERE department_id = 0;
CREATE INDEX record_department_index ON record (rayon_id, organization_id, department_id) WHERE department_id <> 0;
oracle indexing plsql oracle11g
What happened when you tried?
– mathguy
Nov 28 '18 at 20:37
What would be the composite index you'd like to emulate? And you do not necessarily need to create functions to use function-based indexes in Oracle - those can actually be based on expressions too.
– Hilarion
Nov 28 '18 at 23:48
@Hilarion, CREATE INDEX record_main_index ON record (rayon_id, organization_id) WHERE department_id = 0; CREATE INDEX record_department_index ON record (rayon_id, organization_id, department_id) WHERE department_id <> 0;
– user3665549
Nov 29 '18 at 9:33
add a comment |
Big table
record (
id number primary key,
city_id number not null,
organization_id number not null,
department_id number not null, -- extra context, can be 0
renew_date date not null -- frequently updated
)
Two kind of query are used:
1.
WITH cte (city_id, organization_id, -- etc...) AS (
-- table join routine...
)
SELECT r.*
FROM record r
INNER JOIN cte t ON r.city_id = t.city_id AND r.organization_id = t.organization_id AND r.department_id = 0
WHERE -- some condition on renew_date... whatever
2.
WITH cte (city_id, organization_id, department_id, -- etc...) AS (
-- same
)
SELECT r.*
FROM record r
INNER JOIN cte t ON r.city_id = t.city_id AND r.organization_id = t.organization_id AND r.department_id = t.department_id
WHERE -- some condition on renew_date or smth else
There are rumors that partial multicolumn (compozite) index can be emulated in Oracle.
https://community.oracle.com/ideas/18213
https://blog.jooq.org/2017/01/18/how-to-emulate-partial-indexes-in-oracle/
Do i need to create a pair of some kind of hash function
CREATE OR REPLACE FUNCTION get_record_index (city_id IN NUMBER, organization_id IN NUMBER, department_id IN NUMBER)
RETURN NUMBER
DETERMINISTIC
AS
BEGIN
IF department_id <> 0 THEN RETURN NULL
ELSE RETURN no_idea_how_to_compute(city_id, organization_id);
END IF;
END;
CREATE OR REPLACE FUNCTION get_record_department_index (city_id IN NUMBER, organization_id IN NUMBER, department_id IN NUMBER)
RETURN NUMBER
DETERMINISTIC
AS
BEGIN
IF department_id = 0 THEN RETURN NULL
ELSE RETURN no_idea_how_to_compute2(city_id, organization_id, department_id);
END IF;
END;
and create two function based index?
upd:
I need smth like that
CREATE INDEX record_main_index ON record (rayon_id, organization_id) WHERE department_id = 0;
CREATE INDEX record_department_index ON record (rayon_id, organization_id, department_id) WHERE department_id <> 0;
oracle indexing plsql oracle11g
Big table
record (
id number primary key,
city_id number not null,
organization_id number not null,
department_id number not null, -- extra context, can be 0
renew_date date not null -- frequently updated
)
Two kind of query are used:
1.
WITH cte (city_id, organization_id, -- etc...) AS (
-- table join routine...
)
SELECT r.*
FROM record r
INNER JOIN cte t ON r.city_id = t.city_id AND r.organization_id = t.organization_id AND r.department_id = 0
WHERE -- some condition on renew_date... whatever
2.
WITH cte (city_id, organization_id, department_id, -- etc...) AS (
-- same
)
SELECT r.*
FROM record r
INNER JOIN cte t ON r.city_id = t.city_id AND r.organization_id = t.organization_id AND r.department_id = t.department_id
WHERE -- some condition on renew_date or smth else
There are rumors that partial multicolumn (compozite) index can be emulated in Oracle.
https://community.oracle.com/ideas/18213
https://blog.jooq.org/2017/01/18/how-to-emulate-partial-indexes-in-oracle/
Do i need to create a pair of some kind of hash function
CREATE OR REPLACE FUNCTION get_record_index (city_id IN NUMBER, organization_id IN NUMBER, department_id IN NUMBER)
RETURN NUMBER
DETERMINISTIC
AS
BEGIN
IF department_id <> 0 THEN RETURN NULL
ELSE RETURN no_idea_how_to_compute(city_id, organization_id);
END IF;
END;
CREATE OR REPLACE FUNCTION get_record_department_index (city_id IN NUMBER, organization_id IN NUMBER, department_id IN NUMBER)
RETURN NUMBER
DETERMINISTIC
AS
BEGIN
IF department_id = 0 THEN RETURN NULL
ELSE RETURN no_idea_how_to_compute2(city_id, organization_id, department_id);
END IF;
END;
and create two function based index?
upd:
I need smth like that
CREATE INDEX record_main_index ON record (rayon_id, organization_id) WHERE department_id = 0;
CREATE INDEX record_department_index ON record (rayon_id, organization_id, department_id) WHERE department_id <> 0;
oracle indexing plsql oracle11g
oracle indexing plsql oracle11g
edited Nov 29 '18 at 9:34
user3665549
asked Nov 28 '18 at 20:22
user3665549user3665549
265
265
What happened when you tried?
– mathguy
Nov 28 '18 at 20:37
What would be the composite index you'd like to emulate? And you do not necessarily need to create functions to use function-based indexes in Oracle - those can actually be based on expressions too.
– Hilarion
Nov 28 '18 at 23:48
@Hilarion, CREATE INDEX record_main_index ON record (rayon_id, organization_id) WHERE department_id = 0; CREATE INDEX record_department_index ON record (rayon_id, organization_id, department_id) WHERE department_id <> 0;
– user3665549
Nov 29 '18 at 9:33
add a comment |
What happened when you tried?
– mathguy
Nov 28 '18 at 20:37
What would be the composite index you'd like to emulate? And you do not necessarily need to create functions to use function-based indexes in Oracle - those can actually be based on expressions too.
– Hilarion
Nov 28 '18 at 23:48
@Hilarion, CREATE INDEX record_main_index ON record (rayon_id, organization_id) WHERE department_id = 0; CREATE INDEX record_department_index ON record (rayon_id, organization_id, department_id) WHERE department_id <> 0;
– user3665549
Nov 29 '18 at 9:33
What happened when you tried?
– mathguy
Nov 28 '18 at 20:37
What happened when you tried?
– mathguy
Nov 28 '18 at 20:37
What would be the composite index you'd like to emulate? And you do not necessarily need to create functions to use function-based indexes in Oracle - those can actually be based on expressions too.
– Hilarion
Nov 28 '18 at 23:48
What would be the composite index you'd like to emulate? And you do not necessarily need to create functions to use function-based indexes in Oracle - those can actually be based on expressions too.
– Hilarion
Nov 28 '18 at 23:48
@Hilarion, CREATE INDEX record_main_index ON record (rayon_id, organization_id) WHERE department_id = 0; CREATE INDEX record_department_index ON record (rayon_id, organization_id, department_id) WHERE department_id <> 0;
– user3665549
Nov 29 '18 at 9:33
@Hilarion, CREATE INDEX record_main_index ON record (rayon_id, organization_id) WHERE department_id = 0; CREATE INDEX record_department_index ON record (rayon_id, organization_id, department_id) WHERE department_id <> 0;
– user3665549
Nov 29 '18 at 9:33
add a comment |
1 Answer
1
active
oldest
votes
You could add a virtual column to the table and then include that column in an index:
ALTER TABLE record ADD zero_dept_id AS (CASE department_id WHEN 0 THEN 0 END);
CREATE INDEX record_paritial_idx ON record (city_id, organization_id, zero_dept_id);
On second thought you may be wanting only the single column index below instead of the multi-column index above.
CREATE INDEX record_paritial_idx ON record (zero_dept_id);
Then in your code instead of using r.department_id = 0
you would use r.zero_dept_id = 0
to use the new index.
No guarantees that this will improve your query performance, but you can certainly give it a try.
For a multi column index that truly prunes out all the non zero department_id entries you may need more virtual columns:
ALTER TABLE record ADD zero_dept_id AS (CASE department_id WHEN 0 THEN 0 END);
ALTER TABLE record ADD zero_dept_city_id AS (CASE department_id WHEN 0 THEN city_id END);
ALTER TABLE record ADD zero_dept_org_id AS (CASE department_id WHEN 0 THEN organization_id END);
CREATE INDEX record_paritial_idx ON record (zero_dept_city_id, zero_dept_org_id, zero_dept_id);
Then in your code make the appropriate substitutions to get this:
r.zero_dept_city_id = t.city_id AND r.zero_dept_org_id = t.organization_id AND r.zero_dept_id = 0
In the last option above, you could possibly drop the zero_dept_id column since the other two virtual columns will only have values in the index when the department id is zero in which case the index would become this:
CREATE INDEX record_paritial_idx ON record (zero_dept_city_id, zero_dept_org_id);
and the query predicate would be:
r.zero_dept_city_id = t.city_id AND r.zero_dept_org_id = t.organization_id
with the department_id = 0
predicate implied by the zero_dept* virtual columns.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53527503%2fhow-to-emulate-partial-multicolumn-compozite-index-in-oracle-11-2%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You could add a virtual column to the table and then include that column in an index:
ALTER TABLE record ADD zero_dept_id AS (CASE department_id WHEN 0 THEN 0 END);
CREATE INDEX record_paritial_idx ON record (city_id, organization_id, zero_dept_id);
On second thought you may be wanting only the single column index below instead of the multi-column index above.
CREATE INDEX record_paritial_idx ON record (zero_dept_id);
Then in your code instead of using r.department_id = 0
you would use r.zero_dept_id = 0
to use the new index.
No guarantees that this will improve your query performance, but you can certainly give it a try.
For a multi column index that truly prunes out all the non zero department_id entries you may need more virtual columns:
ALTER TABLE record ADD zero_dept_id AS (CASE department_id WHEN 0 THEN 0 END);
ALTER TABLE record ADD zero_dept_city_id AS (CASE department_id WHEN 0 THEN city_id END);
ALTER TABLE record ADD zero_dept_org_id AS (CASE department_id WHEN 0 THEN organization_id END);
CREATE INDEX record_paritial_idx ON record (zero_dept_city_id, zero_dept_org_id, zero_dept_id);
Then in your code make the appropriate substitutions to get this:
r.zero_dept_city_id = t.city_id AND r.zero_dept_org_id = t.organization_id AND r.zero_dept_id = 0
In the last option above, you could possibly drop the zero_dept_id column since the other two virtual columns will only have values in the index when the department id is zero in which case the index would become this:
CREATE INDEX record_paritial_idx ON record (zero_dept_city_id, zero_dept_org_id);
and the query predicate would be:
r.zero_dept_city_id = t.city_id AND r.zero_dept_org_id = t.organization_id
with the department_id = 0
predicate implied by the zero_dept* virtual columns.
add a comment |
You could add a virtual column to the table and then include that column in an index:
ALTER TABLE record ADD zero_dept_id AS (CASE department_id WHEN 0 THEN 0 END);
CREATE INDEX record_paritial_idx ON record (city_id, organization_id, zero_dept_id);
On second thought you may be wanting only the single column index below instead of the multi-column index above.
CREATE INDEX record_paritial_idx ON record (zero_dept_id);
Then in your code instead of using r.department_id = 0
you would use r.zero_dept_id = 0
to use the new index.
No guarantees that this will improve your query performance, but you can certainly give it a try.
For a multi column index that truly prunes out all the non zero department_id entries you may need more virtual columns:
ALTER TABLE record ADD zero_dept_id AS (CASE department_id WHEN 0 THEN 0 END);
ALTER TABLE record ADD zero_dept_city_id AS (CASE department_id WHEN 0 THEN city_id END);
ALTER TABLE record ADD zero_dept_org_id AS (CASE department_id WHEN 0 THEN organization_id END);
CREATE INDEX record_paritial_idx ON record (zero_dept_city_id, zero_dept_org_id, zero_dept_id);
Then in your code make the appropriate substitutions to get this:
r.zero_dept_city_id = t.city_id AND r.zero_dept_org_id = t.organization_id AND r.zero_dept_id = 0
In the last option above, you could possibly drop the zero_dept_id column since the other two virtual columns will only have values in the index when the department id is zero in which case the index would become this:
CREATE INDEX record_paritial_idx ON record (zero_dept_city_id, zero_dept_org_id);
and the query predicate would be:
r.zero_dept_city_id = t.city_id AND r.zero_dept_org_id = t.organization_id
with the department_id = 0
predicate implied by the zero_dept* virtual columns.
add a comment |
You could add a virtual column to the table and then include that column in an index:
ALTER TABLE record ADD zero_dept_id AS (CASE department_id WHEN 0 THEN 0 END);
CREATE INDEX record_paritial_idx ON record (city_id, organization_id, zero_dept_id);
On second thought you may be wanting only the single column index below instead of the multi-column index above.
CREATE INDEX record_paritial_idx ON record (zero_dept_id);
Then in your code instead of using r.department_id = 0
you would use r.zero_dept_id = 0
to use the new index.
No guarantees that this will improve your query performance, but you can certainly give it a try.
For a multi column index that truly prunes out all the non zero department_id entries you may need more virtual columns:
ALTER TABLE record ADD zero_dept_id AS (CASE department_id WHEN 0 THEN 0 END);
ALTER TABLE record ADD zero_dept_city_id AS (CASE department_id WHEN 0 THEN city_id END);
ALTER TABLE record ADD zero_dept_org_id AS (CASE department_id WHEN 0 THEN organization_id END);
CREATE INDEX record_paritial_idx ON record (zero_dept_city_id, zero_dept_org_id, zero_dept_id);
Then in your code make the appropriate substitutions to get this:
r.zero_dept_city_id = t.city_id AND r.zero_dept_org_id = t.organization_id AND r.zero_dept_id = 0
In the last option above, you could possibly drop the zero_dept_id column since the other two virtual columns will only have values in the index when the department id is zero in which case the index would become this:
CREATE INDEX record_paritial_idx ON record (zero_dept_city_id, zero_dept_org_id);
and the query predicate would be:
r.zero_dept_city_id = t.city_id AND r.zero_dept_org_id = t.organization_id
with the department_id = 0
predicate implied by the zero_dept* virtual columns.
You could add a virtual column to the table and then include that column in an index:
ALTER TABLE record ADD zero_dept_id AS (CASE department_id WHEN 0 THEN 0 END);
CREATE INDEX record_paritial_idx ON record (city_id, organization_id, zero_dept_id);
On second thought you may be wanting only the single column index below instead of the multi-column index above.
CREATE INDEX record_paritial_idx ON record (zero_dept_id);
Then in your code instead of using r.department_id = 0
you would use r.zero_dept_id = 0
to use the new index.
No guarantees that this will improve your query performance, but you can certainly give it a try.
For a multi column index that truly prunes out all the non zero department_id entries you may need more virtual columns:
ALTER TABLE record ADD zero_dept_id AS (CASE department_id WHEN 0 THEN 0 END);
ALTER TABLE record ADD zero_dept_city_id AS (CASE department_id WHEN 0 THEN city_id END);
ALTER TABLE record ADD zero_dept_org_id AS (CASE department_id WHEN 0 THEN organization_id END);
CREATE INDEX record_paritial_idx ON record (zero_dept_city_id, zero_dept_org_id, zero_dept_id);
Then in your code make the appropriate substitutions to get this:
r.zero_dept_city_id = t.city_id AND r.zero_dept_org_id = t.organization_id AND r.zero_dept_id = 0
In the last option above, you could possibly drop the zero_dept_id column since the other two virtual columns will only have values in the index when the department id is zero in which case the index would become this:
CREATE INDEX record_paritial_idx ON record (zero_dept_city_id, zero_dept_org_id);
and the query predicate would be:
r.zero_dept_city_id = t.city_id AND r.zero_dept_org_id = t.organization_id
with the department_id = 0
predicate implied by the zero_dept* virtual columns.
edited Nov 29 '18 at 0:24
answered Nov 29 '18 at 0:07
SentinelSentinel
5,06011221
5,06011221
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53527503%2fhow-to-emulate-partial-multicolumn-compozite-index-in-oracle-11-2%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What happened when you tried?
– mathguy
Nov 28 '18 at 20:37
What would be the composite index you'd like to emulate? And you do not necessarily need to create functions to use function-based indexes in Oracle - those can actually be based on expressions too.
– Hilarion
Nov 28 '18 at 23:48
@Hilarion, CREATE INDEX record_main_index ON record (rayon_id, organization_id) WHERE department_id = 0; CREATE INDEX record_department_index ON record (rayon_id, organization_id, department_id) WHERE department_id <> 0;
– user3665549
Nov 29 '18 at 9:33