Django-alkalmazások áttelepítése más adatbázisokból SQL Server

Ez a cikk útmutatást nyújt a Django-alkalmazások PostgreSQL-ből, MySQL-ből vagy SQLite-ból SQL Serverre történő migrálásához a mssql-django háttérrendszer használatával.

Overview

Django ORM-je elvonja a legtöbb adatbázis-különbséget, de bizonyos viselkedések és SQL-dialektusok a háttérrendszerben eltérőek. Ez az útmutató a SQL Server való migrálás során felmerülő főbb különbségeket ismerteti.

1. lépés: Az mssql-django telepítése

Telepítse a mssql-django csomagot és annak függőségeit:

pip install mssql-django

Győződjön meg arról, hogy a SQL Server Microsoft ODBC-illesztőprogramja telepítve van. A platformspecifikus utasításokért lásd: Mssql-django telepítése .

2. lépés: Konfiguráció frissítése DATABASE

Cserélje le a meglévő adatbázis-konfigurációt a következő helyen settings.py:

# Example: From PostgreSQL
# DATABASES = {
#     "default": {
#         "ENGINE": "django.db.backends.postgresql",
#         "NAME": "mydb",
#     },
# }

# To SQL Server
DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<your-username>",
        "PASSWORD": "<your-password>",
        "HOST": "<your-server>",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
        },
    },
}

3. lépés: Új migrálások létrehozása

Kezdje a SQL Server tiszta áttelepítési előzményeivel:

# Remove existing migration files (keep __init__.py)
# Then regenerate
python manage.py makemigrations
python manage.py migrate

Important

Adatok átvitele adatmigrálással vagy külön ETL-folyamattal. Ne kísérelje meg a PostgreSQL- vagy MySQL-migrációs fájlok futtatását az SQL Serveren.

A PostgreSQL főbb eltérései

Funkció PostgreSQL SQL Server (mssql-django)
Automatikus növekmény SERIAL / BIGSERIAL IDENTITY(1,1)
Logikai típus Natív boolean bit (0 vagy 1)
Szövegmezők text (korlátlan) nvarchar(max)
JSON-támogatás Natív jsonb nvarchar(max) JSON-függvényekkel (SQL Server 2016+)
Tömb típusú mezők ArrayField Nem támogatott. Használjon kapcsolódó táblát vagy JSON-t.
HStore mezők HStoreField Nem támogatott. A JSONField használható helyette.
Tartománymezők IntegerRangeField, BigIntegerRangeField, DateRangeFieldDateTimeRangeField Nem támogatott. Használjon két külön mezőt.
Teljes szöveges keresés SearchVector, SearchRank Nyers SQL használata SQL Server teljes szöveges kereséssel.
DISTINCT ON Támogatott Nem támogatott. Használjon GROUP BY vagy allekérdezéseket.
DateTimeField időzónával együtt timestamp with time zone datetimeoffset (mikor USE_TZ=True) vagy datetime2

Lecserélendő PostgreSQL-specifikus funkciók

Ha a kód PostgreSQL-specifikus funkciókat django.contrib.postgreshasznál, cserélje le őket:

# PostgreSQL ArrayField - replace with JSONField or related table
# Before
from django.contrib.postgres.fields import ArrayField
tags = ArrayField(models.CharField(max_length=50))

# After (using JSONField)
tags = models.JSONField(default=list)

# PostgreSQL HStoreField - replace with JSONField
# Before
from django.contrib.postgres.fields import HStoreField
metadata = HStoreField()

# After
metadata = models.JSONField(default=dict)

Főbb különbségek a MySQL-től

Funkció MySQL SQL Server (mssql-django)
Automatikus növekmény AUTO_INCREMENT IDENTITY(1,1)
Logikai típus tinyint(1) bit
Szövegmezők longtext nvarchar(max)
JSON-támogatás Natív JSON (5.7 és újabb) nvarchar(max) JSON-függvényekkel
Collation Oszloponként konfigurálható Példány- vagy adatbázisszinten (felülbírálás a COLLATE beállítással)
DateTimeField datetime(6) datetimeoffset vagy datetime2

Főbb különbségek az SQLite-től

Funkció SQLite SQL Server (mssql-django)
Típuskényszerítés Rugalmas gépelés Szigorú típusérvényesítés
Egyidejű írások Limited Teljes konkurenciatámogatás
Kapcsolatok maximális száma Gyakorlatilag 1 író Kapcsolatpoolozás sok párhuzamos kapcsolat esetén
DateTimeField Szövegként tárolva datetimeoffset vagy datetime2

Rendezési különbségek

A rendezési szabály határozza meg, hogy az SQL Server hogyan hasonlítja össze és rendezi a szövegeket. Ez a Váratlan viselkedés egyik leggyakoribb forrása a PostgreSQL-ből vagy a MySQL-ből való migráláskor.

Betűérzékenység

A SQL Server alapértelmezett rendezése (SQL_Latin1_General_CP1_CI_AS) nem érzékeny a kis- és nagybetűkre. A PostgreSQL alapértelmezés szerint megkülönbözteti a kis- és nagybetűk értékét.

Ez a viselkedés azt jelenti, hogy a migráció után azok a lekérdezések, amelyek korábban különbséget tettek a(z) "Smith" és a(z) "smith" között, ezeket egyenlőnek tekintik:

# On PostgreSQL: returns only exact case matches
# On SQL Server (default collation): returns both "Smith" and "smith"
User.objects.filter(last_name="Smith")

Ha az alkalmazás megkülönbözteti a kis- és nagybetűket, két lehetősége van:

  • Módosítsa az adatbázis vagy az oszlop rendezését egy kis- és nagybetűket megkülönböztető változatra:

    -- Database-level (affects all new columns)
    ALTER DATABASE [<your-database>] COLLATE Latin1_General_CS_AS;
    
    -- Column-level (for specific columns)
    ALTER TABLE [<your-table>]
    ALTER COLUMN [<column-name>] NVARCHAR (150) COLLATE Latin1_General_CS_AS;
    
  • Célzott lekérdezésekhez használja a Django __exact lookupját nyers SQL-ben, kolláció felülbírálásával.

Ékezetérzékenység

Az SQL Server alapértelmezett rendezési sorrendje megkülönbözteti az ékezeteket (AS), ami megfelel a PostgreSQL viselkedésének. Az olyan karaktereket, mint a é és e, különbözőként kezeljük. Ha ékezetérzéketlen összehasonlításokra van szüksége, használjon olyan kollációt, amelynek a neve _AI végződésű.

Rendezés konfigurálása az mssql-django-ban

Felülbírálja az adatbázis-konfigurációban lévő szövegmező-keresések alapértelmezett rendezési beállításait:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "collation": "Latin1_General_CS_AS",  # Case-sensitive
        },
    },
}

Note

A mssql-djangocollation beállítása a Django ORM-keresések által létrehozott LIKE és összehasonlítási műveletekben használt összehasonlítási sorrendet vezérli. Ez nem módosítja az adatbázis meglévő oszlopainak rendezést. A tárolt oszlopok rendezésének módosításához használja ALTER TABLE / ALTER COLUMN az utasításokat. További információ: SQL Server rendezési dokumentáció.

4. lépés: Egyéni SQL frissítése

Ha a kód nyers SQL-t tartalmaz, frissítse SQL Server szintaxisra:

# PostgreSQL syntax
# cursor.execute("SELECT * FROM products LIMIT 10 OFFSET 20")

# SQL Server syntax
cursor.execute("SELECT * FROM products ORDER BY id OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY")

Gyakori SQL-szintaxisbeli különbségek:

Operation PostgreSQL/MySQL SQL Server
Eredmények korlátozása LIMIT 10 TOP 10 vagy OFFSET ... FETCH NEXT ...
Sztringösszefűzés \|\| (PG) / CONCAT() + vagy CONCAT()
Logikai literálok TRUE / FALSE 1 / 0
Aktuális időbélyeg NOW() GETDATE(), vagy SYSDATETIME()SYSDATETIMEOFFSET() időzóna-tudatos értékek esetén
HA NEM LÉTEZIK CREATE TABLE IF NOT EXISTS Ellenőrizze a sys.objects elemet, vagy használja a IF NOT EXISTS elemet

Tranzakcióelkülönítési különbségek

A PostgreSQL az MVCC-t (többverziós egyidejűség-vezérlést) használja az elkülönítési szinthez READ COMMITTED . Az olvasók soha nem blokkolják az írókat, az írók pedig soha nem blokkolják az olvasókat.

A SQL Server alapértelmezés szerint READ COMMITTED zárolást alkalmaz, ami azt jelenti, hogy az olvasási lekérdezéseknek várakozniuk kellhet, amíg az írási tranzakciók befejeződnek. Ha az alkalmazás a migrálás után fokozott blokkolást tapasztal, fontolja meg az adatbázis engedélyezését READ COMMITTED SNAPSHOT :

ALTER DATABASE [<your-database>]
SET READ_COMMITTED_SNAPSHOT ON;

Ez úgy módosítja az SQL Server READ COMMITTED beállítását, hogy zárolás helyett sorverzió-kezelést használjon (a PostgreSQL MVCC-jéhez hasonlóan). Az olvasók az aktív írókra való várakozás nélkül látják a sor utolsó véglegesített verzióját.

Note

READ COMMITTED SNAPSHOT további tempdb helyet igényel a sorverziókhoz. Tesztelje valós terhelés mellett, mielőtt éles környezetben engedélyezi. További információ: Tranzakciókezelés az mssql-django-ban.

5. lépés: Adatok migrálása

Az adatmigrálási stratégia az adathalmaz méretétől függ:

Kis adathalmazok (<500 MB)

Használja a Django dumpdata/loaddata elemét:

# On the source database
python manage.py dumpdata --natural-foreign --natural-primary -o data.json

# Switch settings.py to SQL Server, then:
python manage.py migrate
python manage.py loaddata data.json

Nagy adathalmazok (>500 MB)

Nagy méretű migrálások esetén speciális eszközökkel elkerülheti a memóriakimerüléssel és az időtúllépéssel kapcsolatos problémákat. A Django ORM-je nem a megfelelő eszköz a tömeges terheléshez ezen a szinten. Kerülje meg ezt az adatok áthelyezése során, majd hagyja, hogy a Django kezelje a sémát és az alkalmazáslogikát.

Tool Legjobb a számára
SQL Server Importálás és Exportálás Varázsló Helyszíni migrálások helyszíni környezetbe grafikus felhasználói felülettel
Azure Data Factory Bármely forrásból az Azure SQL-be, beleértve a hibrid forgatókönyveket is
Azure Database Migration Service Nagyméretű migrálások beépített ellenőrzéssel és visszaállítással
mssql-python tömeges másolás az Apache Arrow használatával Egyéni Python-adatcsatornák, amelyek maximális adatátviteli sebességet igényelnek az SQL Server, az Azure SQL Database és a Fabricben lévő SQL-adatbázis között

Áttelepítés utáni ellenőrzés

A migrálás után ellenőrizze az identitás kezdőértékének következetességét az automatikusan növekvő oszlopok esetében:

-- Check identity seed and current value for all tables
SELECT 
    TABLE_NAME,
    IDENT_SEED(TABLE_SCHEMA + '.' + TABLE_NAME) AS IdentitySeed,
    IDENT_INCR(TABLE_SCHEMA + '.' + TABLE_NAME) AS IdentityIncrement,
    IDENT_CURRENT(TABLE_SCHEMA + '.' + TABLE_NAME) AS CurrentIdentity
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
    AND OBJECTPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME), 'TableHasIdentity') = 1
ORDER BY TABLE_NAME;

Ha CurrentIdentity meghaladja a(z) IdentitySeed + record_count értéket, újramagozás:

DBCC CHECKIDENT ('your_table', RESEED, new_seed);