diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 08a5947a9e..e37f833879 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -27,10 +27,6 @@
  *
  */
 
-#ifdef WIN32
-#define FD_SETSIZE 1024			/* must set before winsock2.h is included */
-#endif
-
 #include "postgres_fe.h"
 
 #include <ctype.h>
@@ -51,7 +47,11 @@
 #include <poll.h>
 #endif
 #else							/* no ppoll(), so use select() */
+#ifdef WIN32
+#define POLL_USING_WINDOWS_SELECT
+#else
 #define POLL_USING_SELECT
+#endif
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
 #endif
@@ -108,6 +108,19 @@ typedef struct socket_set
 
 #endif							/* POLL_USING_SELECT */
 
+#ifdef POLL_USING_WINDOWS_SELECT
+#define SOCKET_WAIT_METHOD "select"
+
+/*----------
+ * On Windows, fd_set is a struct that's effectively
+ *		u_int	fd_count;
+ *		SOCKET	fd_array[FLEXIBLE_ARRAY_MEMBER];
+ *----------
+ */
+typedef fd_set socket_set;
+
+#endif							/* POLL_USING_WINDOWS_SELECT */
+
 /*
  * Multi-platform pthread implementations
  */
@@ -6740,6 +6753,70 @@ socket_has_input(socket_set *sa, int fd, int idx)
 
 #endif							/* POLL_USING_SELECT */
 
+#ifdef POLL_USING_WINDOWS_SELECT
+
+static socket_set *
+alloc_socket_set(int count)
+{
+	socket_set *sa;
+
+	sa = (socket_set *) pg_malloc(offsetof(socket_set, fd_array) +
+								  sizeof(SOCKET) * count);
+	sa->fd_count = 0;
+	return sa;
+}
+
+static void
+free_socket_set(socket_set *sa)
+{
+	pg_free(sa);
+}
+
+static void
+clear_socket_set(socket_set *sa)
+{
+	FD_ZERO(sa);
+}
+
+static void
+add_socket_to_set(socket_set *sa, int fd, int idx)
+{
+	/*
+	 * We do not use FD_SET() here, first because it enforces a maximum array
+	 * length of FD_SETSIZE which is not relevant, and second because it
+	 * uselessly de-duplicates entries, requiring O(N^2) time to add N FDs to
+	 * the set.
+	 */
+	Assert(idx == sa->fd_count);
+	sa->fd_array[sa->fd_count++] = fd;
+}
+
+static int
+wait_on_socket_set(socket_set *sa, int64 usecs)
+{
+	if (usecs > 0)
+	{
+		struct timeval timeout;
+
+		timeout.tv_sec = usecs / 1000000;
+		timeout.tv_usec = usecs % 1000000;
+		/* Note that Windows ignores select's first argument */
+		return select(0, sa, NULL, NULL, &timeout);
+	}
+	else
+	{
+		return select(0, sa, NULL, NULL, NULL);
+	}
+}
+
+static bool
+socket_has_input(socket_set *sa, int fd, int idx)
+{
+	return (FD_ISSET(fd, sa) != 0);
+}
+
+#endif							/* POLL_USING_WINDOWS_SELECT */
+
 
 /* partial pthread implementation for Windows */
 
