Извините, это - Python вместо C#, но по крайней мере результаты корректны:
def ColIdxToXlName(idx):
if idx < 1:
raise ValueError("Index is too small")
result = ""
while True:
if idx > 26:
idx, r = divmod(idx - 1, 26)
result = chr(r + ord('A')) + result
else:
return chr(idx + ord('A') - 1) + result
for i in xrange(1, 1024):
print "%4d : %s" % (i, ColIdxToXlName(i))
Заявление об ограничении ответственности: я не пробовал этого.
Я считаю, что вам необходимо реализовать собственный сервер базы данных. В Интернете есть несколько примеров, которые показывают, как реализовать серверную часть базы данных с пулом соединений.
Использование пула соединений, вероятно, будет хорошим решением для вашего случая, поскольку сетевые соединения остаются открытыми, когда соединения возвращаются в бассейн.
Оба сообщения используют MySQL - возможно, вы сможете использовать аналогичные методы с Postgresql.
Изменить:
В транке Django отредактируйте django / db / __ init__. py
и закомментируйте строку:
signals.request_finished.connect(close_connection)
Этот обработчик сигнала заставляет его отключаться от базы данных после каждого запроса. Я не знаю, каковы будут все побочные эффекты от этого, но нет никакого смысла начинать новое соединение после каждого запроса; это снижает производительность, как вы заметили.
Я использую это сейчас, но я не проводил полного набора тестов, чтобы увидеть, не сломается ли что-нибудь.
Я не знаю, почему все думают, что это необходимо новый бэкэнд, специальный пул подключений или другие сложные решения. Это кажется очень простым, хотя я не сомневаюсь, что есть некоторые неясные подводные камни, которые заставили их сделать это в первую очередь - с которыми следует разбираться более разумно; Как вы заметили, накладные расходы в 5 мс на каждый запрос - это довольно много для высокопроизводительного сервиса. (У меня уходит 150 мсек - я еще не понял почему.)
Редактировать: еще одно необходимое изменение находится в django / middleware / transaction.py; удалите два теста transaction.is_dirty () и всегда вызывайте commit () или rollback (). В противном случае транзакция не будет зафиксирована, если она будет только читать из базы данных, в результате чего блокировки останутся открытыми, которые следует закрыть.
Я сделал небольшой пользовательский бэкэнд psycopg2, который реализует постоянное соединение с использованием глобальной переменной.
Благодаря этому я смог улучшить количество запросов в секунду с 350 до 1600 (на очень простой странице с несколькими вариантами выбора).
Просто сохраните его в файле с именем base.py
в любом каталоге (например, postgresql_psycopg2_persistent) и установите в настройках
DATABASE_ENGINE имя проекта.postgresql_psycopg2_persistent
ПРИМЕЧАНИЕ !!! код не является потокобезопасным - вы не можете использовать его с потоками python из-за неожиданных результатов, в случае mod_wsgi используйте режим демона prefork с thread = 1
# Custom DB backend postgresql_psycopg2 based
# implements persistent database connection using global variable
from django.db.backends.postgresql_psycopg2.base import DatabaseError, DatabaseWrapper as BaseDatabaseWrapper, \
IntegrityError
from psycopg2 import OperationalError
connection = None
class DatabaseWrapper(BaseDatabaseWrapper):
def _cursor(self, *args, **kwargs):
global connection
if connection is not None and self.connection is None:
try: # Check if connection is alive
connection.cursor().execute('SELECT 1')
except OperationalError: # The connection is not working, need reconnect
connection = None
else:
self.connection = connection
cursor = super(DatabaseWrapper, self)._cursor(*args, **kwargs)
if connection is None and self.connection is not None:
connection = self.connection
return cursor
def close(self):
if self.connection is not None:
self.connection.commit()
self.connection = None
Или вот потокобезопасный, но потоки python не использовать несколько ядер, поэтому такого прироста производительности, как у предыдущего, вы не получите. Вы также можете использовать этот метод с несколькими процессами.
# Custom DB backend postgresql_psycopg2 based
# implements persistent database connection using thread local storage
from threading import local
from django.db.backends.postgresql_psycopg2.base import DatabaseError, \
DatabaseWrapper as BaseDatabaseWrapper, IntegrityError
from psycopg2 import OperationalError
threadlocal = local()
class DatabaseWrapper(BaseDatabaseWrapper):
def _cursor(self, *args, **kwargs):
if hasattr(threadlocal, 'connection') and threadlocal.connection is \
not None and self.connection is None:
try: # Check if connection is alive
threadlocal.connection.cursor().execute('SELECT 1')
except OperationalError: # The connection is not working, need reconnect
threadlocal.connection = None
else:
self.connection = threadlocal.connection
cursor = super(DatabaseWrapper, self)._cursor(*args, **kwargs)
if (not hasattr(threadlocal, 'connection') or threadlocal.connection \
is None) and self.connection is not None:
threadlocal.connection = self.connection
return cursor
def close(self):
if self.connection is not None:
self.connection.commit()
self.connection = None
Попробуйте PgBouncer - облегченный пул соединений для PostgreSQL. Особенности: