diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 0b31f55..e4b411f 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -9117,7 +9117,7 @@ copy_relation_data(SMgrRelation src, SMgrRelation dst,
 		/* If we got a cancel signal during the copy of the data, quit */
 		CHECK_FOR_INTERRUPTS();
 
-		smgrread(src, forkNum, blkno, buf);
+		smgrread(src, forkNum, blkno, buf, BAS_BULKREAD);
 
 		if (!PageIsVerified(page, blkno))
 			ereport(ERROR,
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index f848391..488cdf1 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -41,6 +41,7 @@
 #include "pg_trace.h"
 #include "pgstat.h"
 #include "postmaster/bgwriter.h"
+#include "storage/buf.h"
 #include "storage/buf_internals.h"
 #include "storage/bufmgr.h"
 #include "storage/ipc.h"
@@ -451,7 +452,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 			if (track_io_timing)
 				INSTR_TIME_SET_CURRENT(io_start);
 
-			smgrread(smgr, forkNum, blockNum, (char *) bufBlock);
+			smgrread(smgr, forkNum, blockNum, (char *) bufBlock, strategy);
 
 			if (track_io_timing)
 			{
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index de4d902..8cda2f9 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -73,8 +73,10 @@
 #include "catalog/pg_tablespace.h"
 #include "common/relpath.h"
 #include "pgstat.h"
+#include "storage/buf.h"
 #include "storage/fd.h"
 #include "storage/ipc.h"
+#include "storage/bufmgr.h"
 #include "utils/guc.h"
 #include "utils/resowner_private.h"
 
@@ -383,6 +385,21 @@ pg_flush_data(int fd, off_t offset, off_t amount)
 	return 0;
 }
 
+/*
+ * pg_fadvise --- advise OS that the cache will need or not
+ *
+ * Not all platforms have posix_fadvise. If it does not support posix_fadvise,
+ * we do nothing about here.
+ */
+int
+pg_fadvise(int fd, off_t offset, off_t amount, int advise)
+{
+#if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED) && defined(POSIX_FADV_RANDOM) && defined(POSIX_FADV_SEQUENTIAL)
+	return posix_fadvise(fd, offset, amount, advise);
+#else
+	return 0;
+#endif
+}
 
 /*
  * fsync_fname -- fsync a file or directory, handling errors properly
@@ -1142,6 +1159,33 @@ OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError)
 }
 
 /*
+ * Controling OS file cache using posix_fadvise()
+ */
+int
+FileCacheAdvise(File file, off_t offset, off_t amount, int advise)
+{
+	return pg_fadvise(VfdCache[file].fd, offset, amount, advise);
+}
+
+/*
+ * Select OS readahead strategy using buffer hint. If we select POSIX_FADV_SEQUENTIAL,
+ * readahead parameter becomes the maximum and can read more faster. On the other hand,
+ * if we select POSIX_FADV_RANDOM, readahead wasn't executed at all and file cache
+ * replace algorithm will be more smart. Because it can calculate correct number of accesses
+ * which are hot data.
+ */
+int
+BufferHintIOAdvise(File file, off_t offset, off_t amount, char *strategy)
+{
+	if(strategy != NULL)
+			/* use maximum readahead setting in kernel, we can read more faster */
+			return FileCacheAdvise(file, offset, amount, POSIX_FADV_SEQUENTIAL);
+	else
+			/* don't use readahead in kernel, so we can more effectively use OS file cache */
+			return FileCacheAdvise(file, offset, amount, POSIX_FADV_RANDOM);
+}
+
+/*
  * close a file when done with it
  */
 void
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index e629181..e8ff0b0 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -653,7 +653,7 @@ mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
  */
 void
 mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
-	   char *buffer)
+	   char *buffer, char *strategy)
 {
 	off_t		seekpos;
 	int			nbytes;
@@ -677,6 +677,7 @@ mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
 				 errmsg("could not seek to block %u in file \"%s\": %m",
 						blocknum, FilePathName(v->mdfd_vfd))));
 
+	BufferHintIOAdvise(v->mdfd_vfd, buffer, BLCKSZ, strategy);
 	nbytes = FileRead(v->mdfd_vfd, buffer, BLCKSZ);
 
 	TRACE_POSTGRESQL_SMGR_MD_READ_DONE(forknum, blocknum,
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index f7f1437..7a38aec 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -50,7 +50,7 @@ typedef struct f_smgr
 	void		(*smgr_prefetch) (SMgrRelation reln, ForkNumber forknum,
 											  BlockNumber blocknum);
 	void		(*smgr_read) (SMgrRelation reln, ForkNumber forknum,
-										  BlockNumber blocknum, char *buffer);
+					  BlockNumber blocknum, char *buffer, char *strategy);
 	void		(*smgr_write) (SMgrRelation reln, ForkNumber forknum,
 						 BlockNumber blocknum, char *buffer, bool skipFsync);
 	BlockNumber (*smgr_nblocks) (SMgrRelation reln, ForkNumber forknum);
@@ -588,9 +588,9 @@ smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
  */
 void
 smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
-		 char *buffer)
+		 char *buffer, char *strategy)
 {
-	(*(smgrsw[reln->smgr_which].smgr_read)) (reln, forknum, blocknum, buffer);
+	(*(smgrsw[reln->smgr_which].smgr_read)) (reln, forknum, blocknum, buffer, strategy);
 }
 
 /*
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index 6dc031e..ca9a16a 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -44,6 +44,8 @@ typedef enum
 /* in globals.c ... this duplicates miscadmin.h */
 extern PGDLLIMPORT int NBuffers;
 
+
+
 /* in bufmgr.c */
 extern bool zero_damaged_pages;
 extern int	bgwriter_lru_maxpages;
diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h
index 2a60229..3922c0a 100644
--- a/src/include/storage/fd.h
+++ b/src/include/storage/fd.h
@@ -68,6 +68,7 @@ extern int	max_safe_fds;
 extern File PathNameOpenFile(FileName fileName, int fileFlags, int fileMode);
 extern File OpenTemporaryFile(bool interXact);
 extern void FileClose(File file);
+extern int	FileCacheAdvise(File file, off_t offset, off_t amount, int advise);
 extern int	FilePrefetch(File file, off_t offset, int amount);
 extern int	FileRead(File file, char *buffer, int amount);
 extern int	FileWrite(File file, char *buffer, int amount);
@@ -75,6 +76,7 @@ extern int	FileSync(File file);
 extern off_t FileSeek(File file, off_t offset, int whence);
 extern int	FileTruncate(File file, off_t offset);
 extern char *FilePathName(File file);
+extern int	BufferHintIOAdvise(File file, off_t offset, off_t amount, char *strategy);
 
 /* Operations that allow use of regular stdio --- USE WITH CAUTION */
 extern FILE *AllocateFile(const char *name, const char *mode);
@@ -113,6 +115,7 @@ extern int	pg_fsync_no_writethrough(int fd);
 extern int	pg_fsync_writethrough(int fd);
 extern int	pg_fdatasync(int fd);
 extern int	pg_flush_data(int fd, off_t offset, off_t amount);
+extern int	pg_fadvise(int fd, off_t offset, off_t amount, int advise);
 extern void fsync_fname(char *fname, bool isdir);
 
 /* Filename components for OpenTemporaryFile */
diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h
index 98b6f13..0c4f14e 100644
--- a/src/include/storage/smgr.h
+++ b/src/include/storage/smgr.h
@@ -92,7 +92,7 @@ extern void smgrextend(SMgrRelation reln, ForkNumber forknum,
 extern void smgrprefetch(SMgrRelation reln, ForkNumber forknum,
 			 BlockNumber blocknum);
 extern void smgrread(SMgrRelation reln, ForkNumber forknum,
-		 BlockNumber blocknum, char *buffer);
+			BlockNumber blocknum, char *buffer, char *strategy);
 extern void smgrwrite(SMgrRelation reln, ForkNumber forknum,
 		  BlockNumber blocknum, char *buffer, bool skipFsync);
 extern BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum);
@@ -118,7 +118,7 @@ extern void mdextend(SMgrRelation reln, ForkNumber forknum,
 extern void mdprefetch(SMgrRelation reln, ForkNumber forknum,
 		   BlockNumber blocknum);
 extern void mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
-	   char *buffer);
+	   char *buffer, char *strategy);
 extern void mdwrite(SMgrRelation reln, ForkNumber forknum,
 		BlockNumber blocknum, char *buffer, bool skipFsync);
 extern BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum);
