Zaloguj się by uzyskać pełen dostęp. Nie masz jeszcze konta? Założ je już teraz w kilka sekund.

Wysłany: 2014-07-04, 23:17


shiny







Wiek: 35
Na forum: 6271 dni
Posty: 14

Piwa: 17

Respekt: 63

Helo?. Od niedawna bawi? si? w MTA j?zykami bazodanowymi (czyli wbudowanymi SQLite i MySQL). Niby nauczy?em si? ju? wykonywa? podstawowe zapytania, ale jak widz?, SQLite jest ponad 10 razy wolniejsze przy wykonywaniu SELECT. Zastosowa?em transakcje, kt?re powinny by? wsz?dzie dla tego j?zyka (zastosowa?em si? do tego poradnika), wykonuj? zapytania 250,000 razy (!) i z tego co zauwa?y?em:
- INSERT w SQLite dzia?a o kilkana?cie, czasem kilkaset milisekund szybciej (!)
- SELECT w SQLite dzia?a o ponad 10 razy wolniej

Dla test?w w??czy?em te? transakcje dla obu j?zyk?w (tak mi poleci? Tey) i w?a?nie od tego czasu zauwa?y?em, ?e SQLite si? "krztusi". Czy da si? to jako? zoptymalizowa??

Dodam te? tekst z log?w, coby udowodni?, ?e rzeczywi?cie SQLite ma problem z wykonywaniem SELECT:
Kod:

[10] INFO: Czas wykonania p?tli - 3917 milisekund.
[10] INFO: Po??czono z baz? danych.
[10] INFO: Pomy?lnie wype?niono tabel? w SQLite. Czas trwania to 3548 milisekund
[10] INFO: Pomy?lnie wype?niono tabel? w MySQL. Czas trwania to 3640 milisekund
[10] INFO: Pomy?lnie wybrano z tabeli. Czas trwania dla SQLite to 1678 milisekund
[10] INFO: Pomy?lnie wybrano z tabeli. Czas trwania dla MySQL to 182 milisekund

A tutaj kod:
local MySQL_HOST  = "HOST"
local MySQL_USER  = "USER"
local MySQL_PASS  = "PASS"
local MySQL_DB    = "DB"
local MySQL_PORT  = 3306

local Connection        = dbConnect("sqlite", "sqlite.db")
local MySQLConnection   = dbConnect("mysql", "dbname=" .. MySQL_DB .. ";host=" .. MySQL_HOST, MySQL_USER, MySQL_PASS, "share=1", "port=" .. MySQL_PORT)
local TABELA            = "TABELA"
local Handler_DB        = nil
local Number            = 250000

addEventHandler("onResourceStart", resourceRoot, function()
    HandleQuery = dbQuery(Connection, "CREATE TABLE IF NOT EXISTS " .. TABELA .. " (Tekst TEXT, ID INTEGER);")
    MySQLQuery = dbQuery(MySQLConnection, "CREATE TABLE IF NOT EXISTS " .. TABELA .. " (Tekst TEXT, ID INT(2);")
    local Result = dbPoll(HandleQuery, -1) and dbFree(HandleQuery) and dbPoll(MySQLQuery, -1) and dbFree(MySQLQuery)
    
    local NOW = getTickCount()
    
    for i = 0, Number do
        print()
    end
    local TIME__ = getTickCount() - NOW
    outputDebugString("Czas wykonania p?tli - " .. TIME__ .. " milisekund.", 3)
    
    if not Connection then
        outputDebugString("Brak po??czenia z baz? danych SQLite.", 1)
    elseif not MySQLConnection then
        outputDebugString("Brak po??czenia z baz? danych MySQL.", 1)
    else
        outputDebugString("Po??czono z baz? danych.", 3)
        Fill_Table()
        Show_Table()
    end
end)

function Fill_Table()
    local NOW = getTickCount()
    SQLite_Query = dbQuery(Connection, "BEGIN TRANSACTION;")
    for i = 0, Number do
        SQLite_Query = dbQuery(Connection, "INSERT OR REPLACE INTO " .. TABELA .. " (Tekst, ID) VALUES (?, ?)", "Tekst nr" .. i, i)
    end
    SQLite_Query = dbQuery(Connection, "END TRANSACTION;")
    local Difference = getTickCount() - NOW
    outputDebugString("Pomy?lnie wype?niono tabel? w SQLite. Czas trwania to " .. Difference .. " milisekund", 3)

    local NOW__ = getTickCount()
    MySQL_Query = dbQuery(MySQLConnection, "START TRANSACTION;")
    for i__ = 0, Number do
        MySQL_Query = dbQuery(Connection, "INSERT INTO " .. TABELA .. " (Tekst, ID) VALUES (?, ?)", "Tekst nr" .. i__, i__)
    end
    MySQL_Query = dbQuery(MySQLConnection, "COMMIT;")
    local Difference__ = getTickCount() - NOW__
    outputDebugString("Pomy?lnie wype?niono tabel? w MySQL. Czas trwania to " .. Difference__ .. " milisekund", 3)
end

function Show_Table()
    local NOW = getTickCount()
    local QUERY__ = dbQuery(Connection, "BEGIN TRANSACTION;")
    local QUERY__ = dbQuery(Connection, "SELECT ID FROM " .. TABELA .. "")
    local QUERY__ = dbQuery(Connection, "END TRANSACTION;")
    local Result = dbPoll(QUERY__, -1) and dbFree(QUERY__)
    local Difference = getTickCount() - NOW
    outputDebugString("Pomy?lnie wybrano z tabeli. Czas trwania dla SQLite to " .. Difference .. " milisekund", 3)
    
    local NOW__ = getTickCount()
    local QUERY____ = dbQuery(MySQLConnection, "START TRANSACTION")
    local QUERY____ = dbQuery(MySQLConnection, "SELECT ID FROM " .. TABELA)
    local QUERY____ = dbQuery(MySQLConnection, "COMMIT;")
    local Result = dbPoll(QUERY____, -1) and dbFree(QUERY____)
    local Difference__ = getTickCount() - NOW__
    outputDebugString("Pomy?lnie wybrano z tabeli. Czas trwania dla MySQL to " .. Difference__ .. " milisekund", 3)
end

addCommandHandler("insert", Fill_Table)
addCommandHandler("show", Show_Table)

I teraz podstawowe pytanie - czy ja robi? co? ?le, czy mo?e ?le u?ywam SQLite, czy po prostu samo SQLite nie daje sobie rady z tak? liczb? zapyta??

Ostatnio zmieniony przez shiny 2014-07-05, 12:56, w całości zmieniany 1 raz  
Postaw piwo autorowi tego posta
 

 
Wysłany: 2014-07-05, 17:45


Riot

3X






Wiek: 30
Na forum: 5870 dni
Posty: 1123
Nick w MP: Riot/3X

Piwa: 286

Respekt: 123
Respekt: 123

Nada?e? indeksy na kolumny kt?re przeszukujesz? ;)

Postaw piwo autorowi tego posta
 

 
Wysłany: 2014-07-05, 19:27


Wielebny







Wiek: 41
Na forum: 5640 dni
Posty: 257
Nick w MP: Wielebny

Piwa: 1693

Respekt: 180
Respekt: 180Respekt: 180

"Riot" napisał/a:

Nada?e? indeksy na kolumny kt?re przeszukujesz? ;)


Nie nada?, ale to powinno by? bez znaczenia - i tak pobiera wszystkie dane z tych tabel. Ale faktycznie w?tkotw?rca nie powinien tworzy? tabel bez indeks?w.

Sprawa jest te? taka, ?e podany kod nie korzysta z bazy danych, tak jakby to by?a baza danych, tylko jak plik tekstowy - ot wrzuca tam dane a p??niej wszystkie pobiera. Jesli faktycznie chcemy porownac te dwie bazy to nale?a?oby faktycznie skorzysta? z kluczy i select?w operuj?cych na podzbiorach danych.

Trzeba miec te? na uwadze, ?e SQLite jest po prostu plikiem na dysku, a po??czenie MySQL mo?e by? ze zdalnym hostem - nie wiem co tam wpisa?e? w MYSQL_HOST, ale je?li to nie jest host lokalny to do komunikacji z MySQL dochodzi te? latencja sieciowa. Opr?cz tego, nawet z serwerem lokalnym mo?na po??czy? si? przez socket TCP i socket UNIXowy. Ten drugi jest szybszy.

Inna sprawa jest taka, ?e odradzam korzystanie zar?wno z transakcji jak i tabel InnoDB. Napisa?em wiele gamemod?w i naprawd? nie mia?em jeszcze potrzeby zachowania atomiczno?ci serii operacji w bazie danych a do typowych operacji tabele MyISAM s? po prostu szybsze.

Postaw piwo autorowi tego posta
 

 
Więcej szczegółów
Wystawiono 1 piw(a):
shiny
Tagi: przyspieszenie :: quotselectquot :: sqlite :: się :: szybciej?
Anonymous





Na forum: 245 dni
Posty: 1



Anonymous Koniecznie zajrzyj na:






Skocz do:  
Wyświetl posty z ostatnich:   
GTAONLINE.PL » JĘZYKI PROGRAMOWANIA » LUA Ten temat jest zablokowany bez możliwości zmiany postów lub pisania odpowiedzi

Nie możesz pisać nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Dodaj temat do Ulubionych
Wersja do druku