I want to write dynamic query from update statement to merge merge statement
'UPDATE ' || T1_TABLENAME || ' t1 ' || 'SET ( ' ||
v_t1_fields || ' ) = (SELECT ' || v_t2_fields || ' FROM ' ||
T2_TEMPTABLE_NAME || ' tmp WHERE ' || v_con || ' ) ' ||
' WHERE EXISTS ( SELECT 1 FROM ' || T2_TEMPTABLE_NAME ||
' tmp WHERE ' || v_con || ' )';
-- HERE v_con = t1.D=t2.D,
v_t1_fields-it can store dynamically-A,B,C
v_t2_fields-it can store dynamically-A,B,C
------------
MERGE INTO TABLE1 t1
USING TABLE2 t2
ON(t1.D=t2.D)
WHEN MATCHED THEN
UPDATE
SET
t1.A=t2.A,
t1.B=t2.B, //update set (t1.A,t1.B,t1.C =t2.A,t2.B,t2.C) not work
t1.C=t2.C;
------------------
'MERGE INTO ' TABLE1 || ' t1 ' ||
' USING ' TABLE2 || ' t2 ' ||
' ON ( ' || v_cons || ' )
when matched then update set ('
|| v_t1_fields || ') = '( || v_t2_fields || ' );' // Its not work--ORA-01747: invalid user.table.column, table.column, or column specification
then i use reg_exp to split the columns
---------------------------
v_Sql := 'MERGE INTO ' TABLE1 || ' t1 ' ||
' USING ' TABLE2 || ' t2 ' ||
' ON ( ' || v_cons || ' )
when matched then update set ('
( ' || regexp_substr(v_t1_fields, '[^,]+', 1, 1) || ' ) = ( ' || regexp_substr(v_t2_fields, '[^,]+', 1, 1) || ' )
( ' || regexp_substr(v_t1_fields, '[^,]+', 1, 2) || ' ) = ( ' || regexp_substr(v_t2_fields, '[^,]+', 1, 2) || ' )
( ' || regexp_substr(v_t1_fields, '[^,]+', 1,3) || ' ) = ( ' || regexp_substr(v_t2_fields, '[^,]+', 1,3) || ' ) ';
this one also not work ----ORA-01747: invalid user.table.column, table.column, or column specification
dynamic update to dynamic merge
while changing merge with update statement
not working
There are few mistakes in concatenation and usage of the MERGE statement.
Try the following dynamic query:
'MERGE INTO '
|| TABLE1
|| ' t1 '
|| ' USING '
|| TABLE2
|| ' t2 '
|| ' ON ( '
|| V_CONS
|| ' ) when matched then update set '
|| REGEXP_SUBSTR(V_T1_FIELDS, '[^,]+', 1, 1)
|| ' = '
|| REGEXP_SUBSTR(V_T2_FIELDS, '[^,]+', 1, 1)
|| ', '
|| REGEXP_SUBSTR(V_T1_FIELDS, '[^,]+', 1, 2)
|| ' = '
|| REGEXP_SUBSTR(V_T2_FIELDS, '[^,]+', 1, 2)
|| ', '
|| REGEXP_SUBSTR(V_T1_FIELDS, '[^,]+', 1, 3)
|| ' = '
|| REGEXP_SUBSTR(V_T2_FIELDS, '[^,]+', 1, 3);
I am assuming that
TABLE1 and TABLE2 are valid table names
V_CONS is a valid condition on tables
V_T1_FIELDS and V_T2_FIELDS contains valid column names of the table
Cheers!!
I have the below code:
v_SQL := '
-- ==========================================================
-- Main Unpivot Table - To move years from column headings
-- to rows values
-- ==========================================================
SELECT
CAST(FieldYear AS Number) FieldYear
, FieldType
, CASE FieldValue
WHEN '''' THEN NULL
ELSE CAST (FieldValue AS Number(38,8))
END FieldValue
FROM
(SELECT ' ||
v_InsertType ||' AS FieldType
,Y1 as ' || CAST(v_FY0 - 5 - v_OffSet AS CHAR) || '
,Y2 as ' || CAST(v_FY0 - 4 - v_OffSet AS CHAR) || '
,Y3 as ' || CAST(v_FY0 - 3 - v_OffSet AS CHAR) || '
,Y4 as ' || CAST(v_FY0 - 2 - v_OffSet AS CHAR) || '
,Y5 as ' || CAST(v_FY0 - 1 - v_OffSet AS CHAR) || '
,Y6 as ' || CAST(v_FY0 - v_OffSet AS CHAR) || '
,Y7 as ' || CAST(v_FY0 + 1 - v_OffSet AS CHAR) || '
,Y8 as ' || CAST(v_FY0 + 2 - v_OffSet AS CHAR) || '
,Y9 as ' || CAST(v_FY0 + 3 - v_OffSet AS CHAR) || '
,Y10 as ' || CAST(v_FY0 + 4 - v_OffSet AS CHAR) || '
,Y11 as ' || CAST(v_FY0 + 5 - v_OffSet AS CHAR) || '
,Y12 as ' || CAST(v_FY0 + 6 - v_OffSet AS CHAR) || '
,Y13 as ' || CAST(v_FY0 + 7 - v_OffSet AS CHAR) || '
,Y14 as ' || CAST(v_FY0 + 8 - v_OffSet AS CHAR) || '
,Y15 as ' || CAST(v_FY0 + 9 - v_OffSet AS CHAR) || '
,Y16 as ' || CAST(v_FY0 + 10 - v_OffSet AS CHAR) || '
,Y17 as ' || CAST(v_FY0 + 11 - v_OffSet AS CHAR) || '
,Y18 as ' || CAST(v_FY0 + 12 - v_OffSet AS CHAR) || '
,Y19 as ' || CAST(v_FY0 + 13 - v_OffSet AS CHAR) || '
,Y20 as ' || CAST(v_FY0 + 14 - v_OffSet AS CHAR) || '
,Y21 as ' || CAST(v_FY0 + 15 - v_OffSet AS CHAR) || '
,Y22 as ' || CAST(v_FY0 + 16 - v_OffSet AS CHAR) || '
,Y23 as ' || CAST(v_FY0 + 17 - v_OffSet AS CHAR) || '
,Y24 as ' || CAST(v_FY0 + 18 - v_OffSet AS CHAR) || '
,Y25 as ' || CAST(v_FY0 + 19 - v_OffSet AS CHAR) || '
,Y26 as ' || CAST(v_FY0 + 20 - v_OffSet AS CHAR) || '
,Y27 as ' || CAST(v_FY0 + 21 - v_OffSet AS CHAR) || '
,Y28 as ' || CAST(v_FY0 + 22 - v_OffSet AS CHAR) || '
,Y29 as ' || CAST(v_FY0 + 23 - v_OffSet AS CHAR) || '
,Y30 as ' || CAST(v_FY0 + 24 - v_OffSet AS CHAR) || '
,Y31 as ' || CAST(v_FY0 + 25 - v_OffSet AS CHAR) || '
,Y32 as ' || CAST(v_FY0 + 26 - v_OffSet AS CHAR) || '
,Y33 as ' || CAST(v_FY0 + 27 - v_OffSet AS CHAR) || '
,Y34 as ' || CAST(v_FY0 + 28 - v_OffSet AS CHAR) || '
,Y35 as ' || CAST(v_FY0 + 29 - v_OffSet AS CHAR) || '
FROM ' ||
v_tblInsertType || ') UP
UNPIVOT
(FieldValue FOR FieldYear IN
(' || CAST(v_FY0 - 5 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 - 4 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 - 3 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 - 2 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 - 1 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 1 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 2 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 3 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 4 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 5 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 6 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 7 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 8 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 9 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 10 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 11 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 12 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 13 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 14 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 15 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 16 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 17 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 18 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 19 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 20 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 21 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 22 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 23 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 24 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 25 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 26 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 27 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 28 - v_OffSet AS CHAR) || '
,' || CAST(v_FY0 + 29 - v_OffSet AS CHAR) || '
)
)AS unpvt
Execute immediate v_SQL;
where v_FY0 is NUMBER(10);v_SQL NVarchar2(4000),v_InsertType VARCHAR2(4000); and v_OffSet Number(10); v_tblInsertType VARCHAR2(4000);
Upon executing, I get: v_FY0 =2018 and v_OffSet = 0;
Upon executing ,i am getting the error - ORA-00923: FROM Keyword not found where expected.
How to resolve this issue and how to get this working.
You can't use as in the from clause.
This query:
select * from (select dummy from dual) as tab
produces error ORA-00933. So simply remove as:
select * from (select dummy from dual) tab
Here is the modified code that gives me the required answer:
v_SQL := '
-- ==========================================================
-- Main Unpivot Table - To move years from column headings
-- to rows values
-- ==========================================================
SELECT
CAST(FieldYear AS Number) FieldYear
, FieldType
, CASE FieldValue
WHEN n'''' THEN NULL
ELSE CAST (FieldValue AS Number(38,8))
END FieldValue
FROM
(SELECT ' ||
v_InsertType ||' AS FieldType
,Y1 as "' || CAST(v_FY0 - 5 - v_OffSet AS CHAR) || '"
,Y2 as "' || CAST(v_FY0 - 4 - v_OffSet AS CHAR) || '"
,Y3 as "' || CAST(v_FY0 - 3 - v_OffSet AS CHAR) || '"
,Y4 as "' || CAST(v_FY0 - 2 - v_OffSet AS CHAR) || '"
,Y5 as "' || CAST(v_FY0 - 1 - v_OffSet AS CHAR) || '"
,Y6 as "' || CAST(v_FY0 - v_OffSet AS CHAR) || '"
,Y7 as "' || CAST(v_FY0 + 1 - v_OffSet AS CHAR) || '"
,Y8 as "' || CAST(v_FY0 + 2 - v_OffSet AS CHAR) || '"
,Y9 as "' || CAST(v_FY0 + 3 - v_OffSet AS CHAR) || '"
,Y10 as "' || CAST(v_FY0 + 4 - v_OffSet AS CHAR) || '"
,Y11 as "' || CAST(v_FY0 + 5 - v_OffSet AS CHAR) || '"
,Y12 as "' || CAST(v_FY0 + 6 - v_OffSet AS CHAR) || '"
,Y13 as "' || CAST(v_FY0 + 7 - v_OffSet AS CHAR) || '"
,Y14 as "' || CAST(v_FY0 + 8 - v_OffSet AS CHAR) || '"
,Y15 as "' || CAST(v_FY0 + 9 - v_OffSet AS CHAR) || '"
,Y16 as "' || CAST(v_FY0 + 10 - v_OffSet AS CHAR) || '"
,Y17 as "' || CAST(v_FY0 + 11 - v_OffSet AS CHAR) || '"
,Y18 as "' || CAST(v_FY0 + 12 - v_OffSet AS CHAR) || '"
,Y19 as "' || CAST(v_FY0 + 13 - v_OffSet AS CHAR) || '"
,Y20 as "' || CAST(v_FY0 + 14 - v_OffSet AS CHAR) || '"
,Y21 as "' || CAST(v_FY0 + 15 - v_OffSet AS CHAR) || '"
,Y22 as "' || CAST(v_FY0 + 16 - v_OffSet AS CHAR) || '"
,Y23 as "' || CAST(v_FY0 + 17 - v_OffSet AS CHAR) || '"
,Y24 as "' || CAST(v_FY0 + 18 - v_OffSet AS CHAR) || '"
,Y25 as "' || CAST(v_FY0 + 19 - v_OffSet AS CHAR) || '"
,Y26 as "' || CAST(v_FY0 + 20 - v_OffSet AS CHAR) || '"
,Y27 as "' || CAST(v_FY0 + 21 - v_OffSet AS CHAR) || '"
,Y28 as "' || CAST(v_FY0 + 22 - v_OffSet AS CHAR) || '"
,Y29 as "' || CAST(v_FY0 + 23 - v_OffSet AS CHAR) || '"
,Y30 as "' || CAST(v_FY0 + 24 - v_OffSet AS CHAR) || '"
,Y31 as "' || CAST(v_FY0 + 25 - v_OffSet AS CHAR) || '"
,Y32 as "' || CAST(v_FY0 + 26 - v_OffSet AS CHAR) || '"
,Y33 as "' || CAST(v_FY0 + 27 - v_OffSet AS CHAR) || '"
,Y34 as "' || CAST(v_FY0 + 28 - v_OffSet AS CHAR) || '"
,Y35 as "' || CAST(v_FY0 + 29 - v_OffSet AS CHAR) || '"
FROM ' ||
v_tblInsertType || ') UP
UNPIVOT
(FieldValue FOR FieldYear IN
("' || CAST(v_FY0 - 5 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 - 4 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 - 3 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 - 2 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 - 1 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 1 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 2 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 3 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 4 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 5 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 6 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 7 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 8 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 9 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 10 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 11 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 12 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 13 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 14 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 15 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 16 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 17 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 18 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 19 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 20 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 21 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 22 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 23 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 24 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 25 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 26 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 27 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 28 - v_OffSet AS CHAR) || '"
,"' || CAST(v_FY0 + 29 - v_OffSet AS CHAR) || '"
)
) unpvt' ;
Execute immediate v_SQL;
This is my stored procedure:
nzsql -u user -pw pass -c "CREATE OR REPLACE PROCEDURE INSERT_LOGIC(varchar(50),varchar(20),varchar(40)) RETURNS BOOL LANGUAGE NZPLSQL AS BEGIN_PROC
DECLARE
t1 ALIAS FOR $1;
t2 ALIAS FOR $2;
t3 ALIAS FOR $3;
BEGIN
INSERT INTO ABC..XYZ
(select '$t1','$t2','$t3' from ABC..PQR limit 10);
END;
END_PROC;"
The ALIAS FOR is the only way I found on the internet to do this but I get the following error:
NOTICE: plpgsql: ERROR during compile of INSERT_LOGIC near line 3
ERROR: syntax error, unexpected ERROR, expecting VARIABLE or WORD at or near "t1Stuff"
How do I access the three "varchar variables" that I pass to the stored procedure inside the same?
Here is an example similar to your requirement and its working. I am using two tables 'tab1' and 'tab2' with following description:
$ nzsql -d test -c "\d tab1"
Table "TAB1"
Attribute | Type | Modifier | Default Value
-----------+---------------+----------+---------------
COL1 | INTEGER | |
COL2 | CHARACTER(10) | |
COL3 | INTEGER | |
Distributed on hash: "COL1"
$ nzsql -d test -c "\d tab2"
Table "TAB2"
Attribute | Type | Modifier | Default Value
-----------+---------------+----------+---------------
C1 | INTEGER | |
C2 | CHARACTER(10) | |
C3 | INTEGER | |
Distributed on hash: "C1"
Following is the stored procedure code that I used:
CREATE OR REPLACE PROCEDURE INSERT_LOGIC(varchar(50),varchar(20),varchar(40))
RETURNS BOOL
LANGUAGE NZPLSQL
AS
BEGIN_PROC
DECLARE
num_args int4;
sql char(100);
t1 ALIAS FOR $1;
t2 ALIAS FOR $2;
t3 ALIAS FOR $3;
BEGIN
num_args := PROC_ARGUMENT_TYPES.count;
RAISE NOTICE 'Number of arguments: %', num_args;
sql := 'INSERT INTO tab2 SELECT ' || t1 || ',' || t2 || ',' || t3 || ' FROM tab1 LIMIT 10 ';
RAISE NOTICE 'SQL Statement: %', sql;
EXECUTE IMMEDIATE sql;
END;
END_PROC;
Hope this will help!
You're attempting to reference variables by putting a $ in front of the name, which is not valid.
Look at the example in the docs.
DECLARE
logtxt ALIAS FOR $1;
curtime timestamp;
BEGIN
curtime := 'now()';
INSERT INTO logtable VALUES (logtxt, curtime);
RETURN curtime;
END
You should try
INSERT INTO ABC..XYZ
(select t1, t2, t3 from ABC..PQR limit 10);
Though it's possible that the column values won't resolve when used this way. If not, build a dynamic statement and execute it instead.
declare sql varchar;
sql := 'insert into abc..xyz select ' || t1 || ',' || t2 || ',' || t3 || ' from abc..pqr limit 10;'
execute immediate sql;
If you're passing values, not column names, as parameters:
declare sql varchar;
sql := 'insert into abc..xyz select ''' || t1 || ''',''' || t2 || ''',''' || t3 || ''' from abc..pqr limit 10;'
execute immediate sql;
My company works with a UI Framework written in PLSQL which interacts with a Java client program.
A lot of queries need to be passed as a VARCHAR2 string to it to be called when needed.
The query
SELECT DISTINCT cod_visum
FROM tbl_visum
WHERE num_firma = 0
AND (code_visum BETWEEN 1 AND 799 OR code_visum BETWEEN 900 AND 999)
AND id_worker IS NULL
OR ( date_valid_to IS NOT NULL
AND p_date_from > NVL (date_valid_to, p_date_from + 1))
ORDER BY 1;
runs fine and returns the expected results when run from the TOAD editor, but when I pass it as a VARCHAR2 to the framework, I keep getting an ORA-00920 (Invalid relational operator) but can't find the cause. (Also the framework catches the exception and only shows me a dialog with the exception number and text >.<)
I've tried several methods of concatinating the variable p_date_from into the VARCHAR2, like
v_sql_norm VARCHAR2 (450)
:= 'SELECT DISTINCT code_visum
FROM tbl_visum
WHERE num_firma = 0
AND (code_visum BETWEEN 1 AND 799 OR code_visum BETWEEN 900 AND 999)
AND id_worker IS NULL
OR ( date_valid_to IS NOT NULL AND '
|| p_date_from
|| ' > NVL(date_valid_to , '
|| (p_date_from + 1)
|| ')) ORDER BY 1';
I already checked the date formats, tried to convert the dates to a string before concatination but everything results in the same exception.
The table used in the query looks like this:
+--------------------+-------+-------------------+
| Column Name | NULL? | DATA TYPE |
+--------------------+-------+-------------------+
| ID_VISUM_ASSIGMENT | N | NUMBER (12) |
| NUM_FIRMA | N | NUMBER (3) |
| CODE_VISUM | N | VARCHAR2 (3 Char) |
| ID_WORKER | Y | NUMBER (10) |
| DATE_VALID_FROM | Y | DATE |
| DATE_VALID_TO | Y | DATE |
+--------------------+-------+-------------------+
Side info: a visum (or visa?) is assigned to a worker starting at a specific date (date_valid_from). It can be assigned to a certain date (date_valid_to), or indefinitely assigned (date_valid_to is NULL).
Thank you in advance, really appreciate any help! :)
edit: yes, cod_visum is a VARCHAR2 but in the query it's used as NUMBER but I also already tried casting it to a number (and mostly it's casted explicitely ^^)
This bit is wrong: the fourth line mixes variable with boilerplate.
OR ( date_valid_to IS NOT NULL AND '
|| p_date_from
|| ' > NVL(date_valid_to , '
|| (p_date_from + 1)
It should be something like
OR ( date_valid_to IS NOT NULL AND '
|| p_date_from
|| ' > NVL(date_valid_to , ('
|| p_date_from
|| ' + 1)'
Also the logic seems wonky, but that's an aside.
I have an elasticsearch cluster containing 10 nodes splited across 3 zones (A, B, C).
The ES configuration file contain:
cluster.routing.allocation.awareness.force.zone.values = "A,B,C";
I have a single index (index1) containing =~ 283674 docs with a size of =~ 231MB.
The setting for this index contain:
"number_of_replicas" : "2", "number_of_shards" : "5",
Shards seems correctly distributed across zone but within a single zone they are not evenly distributed (see table below, E.g. Zone C | S = shard, (P = Primary | S = Secondary)
What can I do to correctly distribute my shards?
++------+----------------------------------------------------+
||Zone A-----------------------------------------------------|
|| | ||
|| Node 1| S1 (P) ||
|| +-----------------------------------------------------+ ||
|| | ||
|| | S2 (S) S4 (S) ||
|| | ||
|| Node 2| ||
|| +-----------------------------------------------------+ ||
|| | ||
|| | ||
|| | S0 (S) S3 (S) ||
|| | ||
|| Node 3| ||
|-------+----------------------------------------------------|
||Zone B-----------------------------------------------------|
|| | ||
|| | S0 (P) ||
|| Node 4| ||
|| +-----------------------------------------------------+ ||
|| | ||
|| | ||
|| | S3 (P) S4 (P) ||
|| Node 5| ||
|| +-----------------------------------------------------+ ||
|| | ||
|| | ||
|| | S1 (S) S2 (S) ||
|| Node 6| ||
|-------+----------------------------------------------------|
||Zone C-----------------------------------------------------|
|| | ||
|| | S0 (S) S1 (S) S2 (P) S3 (S) S4 (S) ||
|| Node 7| ||
|| +------------------------------------------------------+ ||
|| | ||
|| | ||
|| | ||
|| Node 8| ||
|| +------------------------------------------------------+ ||
|| | ||
|| | ||
|| | ||
|| Node 9| ||
|| +------------------------------------------------------+ ||
|| | ||
|| | ||
|| - ||
|| Node 10 ||
|------------------------------------------------------------|
+------------------------------------------------------------+
I fixed the issue by forcing the number of shard per host and changing the number of primary / secondary per index:
index.number_of_shards = "5";
index.number_of_replicas = "3";
index.routing.allocation.total_shards_per_node = "2";
This results in 2 shards per node evenly distributed across zone.