diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 798c92a..e99f264 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -2168,7 +2168,8 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
 					  -1 /* varlena array */ ,
 					  sizeof(Oid) /* OID's typlen */ ,
 					  true /* OID's typbyval */ ,
-					  'i' /* OID's typalign */ );
+					  'i' /* OID's typalign */ ,
+					  false /* no inplace update */ );
 	}
 	repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a);
 	repl_repl[Anum_pg_extension_extconfig - 1] = true;
@@ -2206,7 +2207,8 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
 					  -1 /* varlena array */ ,
 					  -1 /* TEXT's typlen */ ,
 					  false /* TEXT's typbyval */ ,
-					  'i' /* TEXT's typalign */ );
+					  'i' /* TEXT's typalign */ ,
+					  false /* no inplace update */ );
 	}
 	repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a);
 	repl_repl[Anum_pg_extension_extcondition - 1] = true;
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 90c2753..6d0d590 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -456,7 +456,8 @@ ExecEvalArrayRef(ArrayRefExprState *astate,
 									astate->refattrlength,
 									astate->refelemlength,
 									astate->refelembyval,
-									astate->refelemalign);
+									astate->refelemalign,
+									false);
 		else
 			resultArray = array_set_slice(array_source, i,
 										  upper.indx, lower.indx,
diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c
index 7ce1cce..369ea0a 100644
--- a/src/backend/utils/adt/array_userfuncs.c
+++ b/src/backend/utils/adt/array_userfuncs.c
@@ -147,7 +147,7 @@ array_push(PG_FUNCTION_ARGS)
 	typalign = my_extra->typalign;
 
 	result = array_set(v, 1, &indx, newelem, isNull,
-					   -1, typlen, typbyval, typalign);
+					   -1, typlen, typbyval, typalign, false);
 
 	/*
 	 * Readjust result's LB to match the input's.  This does nothing in the
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 438c3d0..ad7e414 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -28,9 +28,10 @@
 
 
 /*
- * GUC parameter
+ * GUC parameters
  */
 bool		Array_nulls = true;
+bool enable_fast_array_update = false;
 
 /*
  * Local definitions
@@ -2023,6 +2024,7 @@ array_get_slice(ArrayType *array,
  *	elmlen: pg_type.typlen for the array's element type
  *	elmbyval: pg_type.typbyval for the array's element type
  *	elmalign: pg_type.typalign for the array's element type
+ *	inplace_update: true, when is possible try to direct update
  *
  * Result:
  *		  A new array is returned, just like the old except for the one
@@ -2045,7 +2047,8 @@ array_set(ArrayType *array,
 		  int arraytyplen,
 		  int elmlen,
 		  bool elmbyval,
-		  char elmalign)
+		  char elmalign,
+		  bool inplace_update)
 {
 	ArrayType  *newarray;
 	int			i,
@@ -2208,11 +2211,22 @@ array_set(ArrayType *array,
 	}
 	else
 	{
+		bool	origin_is_null;
+
 		offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
 		elt_ptr = array_seek(ARR_DATA_PTR(array), 0, oldnullbitmap, offset,
 							 elmlen, elmbyval, elmalign);
+
+		origin_is_null = array_get_isnull(oldnullbitmap, offset);
+
+		if (inplace_update && !isNull && !origin_is_null && enable_fast_array_update)
+		{
+			ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign, elt_ptr);
+			return array;
+		}
+
 		lenbefore = (int) (elt_ptr - ARR_DATA_PTR(array));
-		if (array_get_isnull(oldnullbitmap, offset))
+		if (origin_is_null)
 			olditemlen = 0;
 		else
 		{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 3107f9c..f4fc263 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1246,6 +1246,16 @@ static struct config_bool ConfigureNamesBool[] =
 		NULL, NULL, NULL
 	},
 	{
+		/* remove from final version! */
+		{"array_fast_update", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
+			gettext_noop("Enable inplace array update."),
+			NULL
+		},
+		&enable_fast_array_update,
+		true,
+		NULL, NULL, NULL
+	},
+	{
 		{"default_with_oids", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
 			gettext_noop("Create new tables with OIDs by default."),
 			NULL
@@ -7959,7 +7969,8 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value)
 					  -1 /* varlena array */ ,
 					  -1 /* TEXT's typlen */ ,
 					  false /* TEXT's typbyval */ ,
-					  'i' /* TEXT's typalign */ );
+					  'i' /* TEXT's typalign */ ,
+					  false /* no inplace update */ );
 	}
 	else
 		a = construct_array(&datum, 1,
@@ -8029,7 +8040,8 @@ GUCArrayDelete(ArrayType *array, const char *name)
 								 -1 /* varlenarray */ ,
 								 -1 /* TEXT's typlen */ ,
 								 false /* TEXT's typbyval */ ,
-								 'i' /* TEXT's typalign */ );
+								 'i' /* TEXT's typalign */ ,
+								 false /* no inplace update */ );
 		else
 			newarray = construct_array(&d, 1,
 									   TEXTOID,
@@ -8097,7 +8109,8 @@ GUCArrayReset(ArrayType *array)
 								 -1 /* varlenarray */ ,
 								 -1 /* TEXT's typlen */ ,
 								 false /* TEXT's typbyval */ ,
-								 'i' /* TEXT's typalign */ );
+								 'i' /* TEXT's typalign */ ,
+								 false /* no inplace update */ );
 		else
 			newarray = construct_array(&d, 1,
 									   TEXTOID,
diff --git a/src/include/utils/array.h b/src/include/utils/array.h
index 95a9249..e31689b 100644
--- a/src/include/utils/array.h
+++ b/src/include/utils/array.h
@@ -219,7 +219,8 @@ extern Datum array_ref(ArrayType *array, int nSubscripts, int *indx,
 		  bool *isNull);
 extern ArrayType *array_set(ArrayType *array, int nSubscripts, int *indx,
 		  Datum dataValue, bool isNull,
-		  int arraytyplen, int elmlen, bool elmbyval, char elmalign);
+		  int arraytyplen, int elmlen, bool elmbyval, char elmalign,
+		  bool inplace_update);
 extern ArrayType *array_get_slice(ArrayType *array, int nSubscripts,
 				int *upperIndx, int *lowerIndx,
 				int arraytyplen, int elmlen, bool elmbyval, char elmalign);
@@ -296,4 +297,7 @@ extern Datum array_agg_finalfn(PG_FUNCTION_ARGS);
  */
 extern Datum array_typanalyze(PG_FUNCTION_ARGS);
 
+/* only for developing purpouses - drop from final version! */
+extern bool enable_fast_array_update;
+
 #endif   /* ARRAY_H */
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 3b2919c..c938da9 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -4175,6 +4175,7 @@ exec_assign_value(PLpgSQL_execstate *estate,
 				ArrayType  *newarrayval;
 				SPITupleTable *save_eval_tuptable;
 				MemoryContext oldcontext;
+				bool		inplace_update;
 
 				/*
 				 * We need to do subscript evaluation, which might require
@@ -4321,6 +4322,14 @@ exec_assign_value(PLpgSQL_execstate *estate,
 					oldarrayval = (ArrayType *) DatumGetPointer(oldarraydatum);
 
 				/*
+				 * support fast update for array scalar variable is enabled only
+				 * when target is a scalar variable and variable holds a local
+				 * copy of some array.
+				 */
+				inplace_update = (((PLpgSQL_datum *) target)->dtype == PLPGSQL_DTYPE_VAR
+							    && ((PLpgSQL_var *) target)->freeval);
+
+				/*
 				 * Build the modified array value.
 				 */
 				newarrayval = array_set(oldarrayval,
@@ -4331,7 +4340,8 @@ exec_assign_value(PLpgSQL_execstate *estate,
 										arrayelem->arraytyplen,
 										arrayelem->elemtyplen,
 										arrayelem->elemtypbyval,
-										arrayelem->elemtypalign);
+										arrayelem->elemtypalign,
+										inplace_update);
 
 				MemoryContextSwitchTo(oldcontext);
 
@@ -4340,11 +4350,34 @@ exec_assign_value(PLpgSQL_execstate *estate,
 				 * at this point.  Note that if the target is a domain,
 				 * coercing the base array type back up to the domain will
 				 * happen within exec_assign_value.
+				 *
+				 * The newarrayval and oldarrayval can be identitic as result
+				 * of implace_update.
 				 */
 				*isNull = false;
-				exec_assign_value(estate, target,
-								  PointerGetDatum(newarrayval),
-								  arrayelem->arraytypoid, isNull);
+
+				if (newarrayval != oldarrayval)
+					exec_assign_value(estate, target,
+									  PointerGetDatum(newarrayval),
+									  arrayelem->arraytypoid, isNull);
+				else
+				{
+					PLpgSQL_var *var = (PLpgSQL_var *) target;
+					Datum newvalue;
+
+					/* we should to recheck domain */
+					Assert(inplace_update);
+					Assert(((PLpgSQL_datum *) target)->dtype == PLPGSQL_DTYPE_VAR);
+
+					newvalue = exec_cast_value(estate,
+										   var->value,
+										   arrayelem->arraytypoid,
+										   var->datatype->typoid,
+										   &(var->datatype->typinput),
+										   var->datatype->typioparam,
+										   var->datatype->atttypmod,
+										   false);
+				}
 				break;
 			}
 
