Вопрос или проблема
Я изучаю PostgresSQL (v16) с помощью PGAdmin 4 (v8.8) и иногда полагаюсь на файлы и скрипты, которыми делятся более опытные аналитики. Однако эта проблема ставит их в тупик: они отправляют мне скрипт, который определяет таблицу с именами полей, написанными заглавными буквами. Когда я запускаю скрипт и пытаюсь импортировать данные в новую таблицу, он выдает ошибку и говорит, что поля не существуют. Имена полей стали строчными. Мне нужно обрамлять имена полей с заглавными или смешанными буквами в кавычки, чтобы они форматировались таким образом, и мне также нужно делать это при именовании поля в SQL-скриптах.
Еще одной узкой местом при импорте .csv файлов является то, что другие аналитики загружают файлы, содержащие до восьми миллионов записей за раз, но у меня возникает ошибка памяти, и мне приходится разбивать файлы на части по три миллиона записей, чтобы загружать их одну за другой.
Я думаю, что эти уникальные ограничения могут быть связаны с общей конфигурацией базы данных, для которой я использовал в основном значения по умолчанию (хотя я установил приложение и данные на вторичный SSD). Если это может помочь, я скопировал настройки “конфигурации сервера” из PGAdmin ниже. Буду признателен за любые идеи о том, что может вызывать эти проблемы. Спасибо!
“конфигурация сервера” из About PGAdmin 4:
ALLOW_SAVE_PASSWORD = True
ALLOW_SAVE_TUNNEL_PASSWORD = False
APP_COPYRIGHT = "Copyright (C) 2013 - 2024, The pgAdmin Development Team"
APP_DEFAULT_EMAIL = "[email protected]"
APP_ICON = "pg-icon"
APP_NAME = "pgAdmin 4"
APP_PATH = "pgadmin"
APP_RELEASE = 8
APP_REVISION = 8
APP_SHORT_NAME = "pgadmin4"
APP_SUFFIX = ""
APP_VERSION = "8.8"
APP_VERSION_EXTN = ('.css', '.js', '.html', '.svg', '.png', '.gif', '.ico')
APP_VERSION_INT = 80800
APP_VERSION_PARAM = "ver"
APP_WIN_PATH = "pgAdmin"
AUTHENTICATION_SOURCES = ['internal']
AUTO_DISCOVER_SERVERS = True
AZURE_CREDENTIAL_CACHE_DIR = "C:\Users\User\AppData\Roaming\pgadmin\azurecredentialcache"
CA_FILE = "E:\PostgreSQL\PGAdmin\pgAdmin 4\web\cacert.pem"
CHECK_EMAIL_DELIVERABILITY = False
CHECK_SESSION_FILES_INTERVAL = 24
CHECK_SUPPORTED_BROWSER = True
COMPRESS_LEVEL = 9
COMPRESS_MIMETYPES = ['text/html', 'text/css', 'text/xml', 'text/javascript', 'application/json', 'application/javascript']
COMPRESS_MIN_SIZE = 500
CONFIG_DATABASE_CONNECTION_MAX_OVERFLOW = 100
CONFIG_DATABASE_CONNECTION_POOL_SIZE = 5
CONFIG_DATABASE_URI = ""
CONSOLE_LOG_FORMAT = "%(asctime)s: %(levelname)s %(name)s: %(message)s"
CONSOLE_LOG_FORMAT_JSON = OrderedDict({'time': 'asctime', 'message': 'message', 'level': 'levelname'})
CONSOLE_LOG_LEVEL = 30
CONTENT_SECURITY_POLICY = "default-src ws: http: data: blob: 'unsafe-inline' 'unsafe-eval';"
COOKIE_DEFAULT_DOMAIN = None
COOKIE_DEFAULT_PATH = "/"
DATA_DIR = "C:\Users\User\AppData\Roaming\pgadmin"
DEBUG = False
DEFAULT_BINARY_PATHS = {'pg': '$DIR/../runtime', 'ppas': ''}
DEFAULT_SERVER = "127.0.0.1"
DEFAULT_SERVER_PORT = 5050
DESKTOP_USER = "[email protected]"
DISABLED_LOCAL_PASSWORD_STORAGE = False
EFFECTIVE_SERVER_PORT = 58873
ENABLE_BINARY_PATH_BROWSING = False
ENABLE_PSQL = True
ENABLE_SERVER_PASS_EXEC_CMD = False
ENHANCED_COOKIE_PROTECTION = True
FILE_LOG_FORMAT = "%(asctime)s: %(levelname)s %(name)s: %(message)s"
FILE_LOG_FORMAT_JSON = OrderedDict({'time': 'asctime', 'message': 'message', 'level': 'levelname'})
FILE_LOG_LEVEL = 30
FIXED_BINARY_PATHS = {'pg': '', 'pg-12': '', 'pg-13': '', 'pg-14': '', 'pg-15': '', 'pg-16': '', 'ppas': '', 'ppas-12': '', 'ppas-13': '', 'ppas-14': '', 'ppas-15': '', 'ppas-16': ''}
HELP_PATH = "../../../docs/en_US/html/"
IS_WIN = True
JSON_LOGGER = False
KERBEROS_CCACHE_DIR = "C:\Users\User\AppData\Roaming\pgadmin\krbccache"
KEYRING_NAME = "Windows WinVaultKeyring"
KRB_APP_HOST_NAME = "127.0.0.1"
KRB_AUTO_CREATE_USER = True
KRB_KTNAME = "<KRB5_KEYTAB_FILE>"
LANGUAGES = {'en': 'English', 'zh': 'Chinese (Simplified)', 'cs': 'Czech', 'fr': 'French', 'de': 'German', 'id': 'Indonesian', 'it': 'Italian', 'ja': 'Japanese', 'ko': 'Korean', 'pl': 'Polish', 'pt_BR': 'Portuguese (Brazilian)', 'ru': 'Russian', 'es': 'Spanish'}
LDAP_ANONYMOUS_BIND = False
LDAP_AUTO_CREATE_USER = True
LDAP_BASE_DN = "<Base-DN>"
LDAP_BIND_FORMAT = "{LDAP_USERNAME_ATTRIBUTE}={LDAP_USERNAME},{LDAP_BASE_DN}"
LDAP_BIND_USER = None
LDAP_CA_CERT_FILE = ""
LDAP_CERT_FILE = ""
LDAP_CONNECTION_TIMEOUT = 10
LDAP_DN_CASE_SENSITIVE = False
LDAP_IGNORE_MALFORMED_SCHEMA = False
LDAP_KEY_FILE = ""
LDAP_SEARCH_BASE_DN = "<Search-Base-DN>"
LDAP_SEARCH_FILTER = "(objectclass=*)"
LDAP_SEARCH_SCOPE = "SUBTREE"
LDAP_SERVER_URI = "ldap://<ip-address>:<port>"
LDAP_USERNAME_ATTRIBUTE = "<User-id>"
LDAP_USE_STARTTLS = False
LOGIN_ATTEMPT_FIELDS = ['password']
LOGIN_BANNER = ""
LOG_FILE = "C:\Users\User\AppData\Roaming\pgadmin\pgadmin4.log"
LOG_ROTATION_AGE = 1440
LOG_ROTATION_MAX_LOG_FILES = 90
LOG_ROTATION_SIZE = 10
MAIL_DEBUG = False
MAIL_PORT = 25
MAIL_SERVER = "localhost"
MAIL_USERNAME = ""
MAIL_USE_SSL = False
MAIL_USE_TLS = False
MASTER_PASSWORD_HOOK = None
MASTER_PASSWORD_REQUIRED = True
MAX_LOGIN_ATTEMPTS = 3
MAX_QUERY_HIST_STORED = 20
MAX_SESSION_IDLE_TIME = 60
MFA_EMAIL_SUBJECT = None
MFA_ENABLED = False
MFA_FORCE_REGISTRATION = False
MFA_SUPPORTED_METHODS = ['email', 'authenticator']
MODULE_BLACKLIST = ['test']
NODE_BLACKLIST = []
OAUTH2_AUTO_CREATE_USER = True
OAUTH2_CONFIG = [{'OAUTH2_NAME': None, 'OAUTH2_DISPLAY_NAME': '<Oauth2 Display Name>', 'OAUTH2_CLIENT_ID': None, 'OAUTH2_CLIENT_SECRET': None, 'OAUTH2_TOKEN_URL': None, 'OAUTH2_AUTHORIZATION_URL': None, 'OAUTH2_SERVER_METADATA_URL': None, 'OAUTH2_API_BASE_URL': None, 'OAUTH2_USERINFO_ENDPOINT': None, 'OAUTH2_SCOPE': None, 'OAUTH2_USERNAME_CLAIM': None, 'OAUTH2_ICON': None, 'OAUTH2_BUTTON_COLOR': None, 'OAUTH2_ADDITIONAL_CLAIMS': None, 'OAUTH2_SSL_CERT_VERIFICATION': True, 'OAUTH2_LOGOUT_URL': None}]
ON_DEMAND_RECORD_COUNT = 1000
OVERRIDE_USER_INACTIVITY_TIMEOUT = True
PASSWORD_LENGTH_MIN = 6
PG_DEFAULT_DRIVER = "psycopg3"
PROXY_X_FOR_COUNT = 1
PROXY_X_HOST_COUNT = 0
PROXY_X_PORT_COUNT = 1
PROXY_X_PREFIX_COUNT = 0
PROXY_X_PROTO_COUNT = 1
SECURITY_EMAIL_SENDER = "no-reply@localhost"
SECURITY_EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE = "Ваш пароль для pgAdmin 4 был изменён"
SECURITY_EMAIL_SUBJECT_PASSWORD_NOTICE = "Ваш пароль pgAdmin 4 был сброшен"
SECURITY_EMAIL_SUBJECT_PASSWORD_RESET = "Инструкции по сбросу пароля для pgAdmin 4"
SECURITY_EMAIL_VALIDATOR_ARGS = {'check_deliverability': False}
SEND_FILE_MAX_AGE_DEFAULT = 31556952
SERVER_HEARTBEAT_TIMEOUT = 30
SERVER_MODE = False
SESSION_COOKIE_DOMAIN = None
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_NAME = "pga4_session"
SESSION_COOKIE_PATH = "/"
SESSION_COOKIE_SAMESITE = "Lax"
SESSION_COOKIE_SECURE = False
SESSION_DB_PATH = "C:\Users\User\AppData\Roaming\pgadmin\sessions"
SESSION_EXPIRATION_TIME = 7
SESSION_SKIP_PATHS = ['/misc/ping']
SETTINGS_SCHEMA_VERSION = 40
SHARED_STORAGE = []
SHOW_GRAVATAR_IMAGE = True
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLITE_PATH = "C:\Users\User\AppData\Roaming\pgadmin\pgadmin4.db"
SQLITE_TIMEOUT = 500
STORAGE_DIR = "C:\Users\User\AppData\Roaming\pgadmin\storage"
STRICT_TRANSPORT_SECURITY = "max-age=31536000; includeSubDomains"
STRICT_TRANSPORT_SECURITY_ENABLED = False
SUPPORT_SSH_TUNNEL = True
TEST_SQLITE_PATH = "C:\Users\User\AppData\Roaming\pgadmin\test_pgadmin4.db"
THREADED_MODE = True
UPGRADE_CHECK_ENABLED = True
UPGRADE_CHECK_KEY = "pgadmin4"
UPGRADE_CHECK_URL = "https://www.pgadmin.org/versions.json"
USER_INACTIVITY_TIMEOUT = 0
WEBSERVER_AUTO_CREATE_USER = True
WEBSERVER_REMOTE_USER = "REMOTE_USER"
WEB_SERVER = "Python"
WTF_CSRF_HEADERS = ['X-pgA-CSRFToken']
X_CONTENT_TYPE_OPTIONS = "nosniff"
X_FRAME_OPTIONS = "SAMEORIGIN"
X_XSS_PROTECTION = "1; mode=block"
Ответ или решение
Проблема с именами полей и регистром в PostgreSQL
Ваша проблема заключается в том, что имена полей, написанные с использованием верхнего или смешанного регистра, не распознаются PostgreSQL, если они не заключены в двойные кавычки. Это связано с тем, как PostgreSQL обрабатывает имена идентификаторов (включая таблицы и колонки).
Почему это происходит?
По умолчанию PostgreSQL преобразует все не заключенные в кавычки идентификаторы в нижний регистр. Следовательно, если вы задаете имя поля как FieldName
, то PostgreSQL автоматически преобразует это имя в fieldname
. Если вы хотите сохранить регистр (например, FieldName
или FIELDNAME
), необходимо заключать идентификаторы в двойные кавычки. Это поведение является частью SQL стандарта и характерно для большинства систем управления базами данных (СУБД).
Пример:
CREATE TABLE my_table (
"FieldName" INT,
"ANOTHER_FIELD" TEXT
);
Если вы после создания таблицы попытаетесь вставить данные без использования кавычек:
INSERT INTO my_table (FieldName, ANOTHER_FIELD) VALUES (1, 'example');
то получите ошибку, так как PostgreSQL не сможет найти поля с такими именами. Вместо этого нужно использовать:
INSERT INTO my_table ("FieldName", "ANOTHER_FIELD") VALUES (1, 'example');
3. Какова ваша стратегия работы с CSV файлами?
При работе с большими объемами данных (например, 8 миллионов записей) важно оптимизировать процесс импорта. Если вы сталкиваетесь с ошибками памяти, возможно, стоит рассмотреть следующие подходы:
-
Разделение файлов. Как вы уже упомянули, деление на части по три миллиона записей является практичным решением. Это уменьшает нагрузку на память и позволяет более эффективно обрабатывать данные.
-
Использование инструмента
COPY
. Процесс импорта данных можно упростить, если использовать командуCOPY
в PostgreSQL. Это позволит значительно ускорить импорт, чем использование многократного выполненияINSERT
. Убедитесь, что ваш CSV файл правильно отформатирован и соответствует ожидаемым вам структурам таблицы.Пример команды:
COPY my_table ("FieldName", "ANOTHER_FIELD") FROM '/path/to/file.csv' DELIMITER ',' CSV HEADER;
-
Настройка конфигурации PostgreSQL. Возможно, дополнительные параметры конфигурации вашего сервера PostgreSQL могут помочь в решении проблемы с памятью. Рассмотрите возможность увеличения следующих параметров в файле
postgresql.conf
:work_mem
maintenance_work_mem
shared_buffers
temp_buffers
Высокие значения могут улучшить производительность, но требуют учета общего объема доступной памяти на сервере.
-
Мониторинг ресурсов. Используйте инструменты мониторинга, чтобы контролировать загрузку CPU и использование памяти во время импорта данных. Это поможет выявить узкие места и оптимизировать операции.
Заключение
Проблема с нераспознаванием имен полей в PostgreSQL может быть решена простой матью использования кавычек. Для работы с большими объемами данных используйте команду COPY
и следите за настройками конфигурации сервера базы данных. Правильное структурирование данных и оптимизация использования памяти значительно ускорят процесс импорта.