मेरी राय में, सर्वर-साइड रिलेशनल डेटाबेस (जैसे SQLite और फायरबर्ड के एम्बेडेड संस्करण को छोड़कर, बाकी सभी की तरह) बनाम एम्बेडेड डेटाबेस (जैसे SQL CE) की तुलना करना गलत है।
उनके बीच मुख्य अंतर यह है कि सामान्य-उद्देश्य वाले सर्वर-साइड रिलेशनल डेटाबेस (जैसे MS SQL, MySQL, Firebird Classic और SuperServer आदि) एक स्वतंत्र सेवा के रूप में स्थापित हैं और आपके मुख्य एप्लिकेशन के दायरे से बाहर चलते हैं . यही कारण है कि वे मल्टी-कोर और मल्टी-सीपीयू आर्किटेक्चर के लिए आंतरिक समर्थन के कारण बेहतर प्रदर्शन कर सकते हैं, गहन डेटाबेस ऑपरेशन के मामले में थ्रूपुट बढ़ाने के लिए प्री-कैशिंग, वीएसएस आदि जैसी ओएस सुविधाओं का उपयोग कर सकते हैं और जितनी मेमोरी का दावा कर सकते हैं आपका OS एकल सेवा/आवेदन प्रदान कर सकता है। इसका मतलब यह भी है कि उनके लिए प्रदर्शन संकेतक आपके एप्लिकेशन से कमोबेश स्वतंत्र हैं, लेकिन काफी हद तक आपके हार्डवेयर पर निर्भर हैं। इस संबंध में मैं कहूंगा कि किसी भी डेटाबेस के सर्वर संस्करण हमेशा एम्बेडेड वाले की तुलना में अधिक प्रदर्शन वाले होते हैं।
SQL CE (Firebird एंबेडेड, SQLite, TurboSQL और कुछ अन्य के साथ) एम्बेडेड DB इंजन हैं , जिसका अर्थ है कि पूरा डेटाबेस एक एकल (या अधिकतम 2) डीएलएल-फाइलों में पैक किया गया है जो आपके आवेदन के साथ वितरित किए जाते हैं। स्पष्ट आकार सीमाओं के कारण (क्या आप अपने 2-3 एमबी लंबे आवेदन के साथ 30 एमबी डीएलएल वितरित करना चाहेंगे?) वे सीधे आपके आवेदन के संदर्भ में चलते हैं और कुल डेटा एक्सेस संचालन के लिए मेमोरी और प्रदर्शन को आपके एप्लिकेशन के अन्य भागों के साथ साझा किया जाता है -- जो उपलब्ध मेमोरी, CPU समय, डिस्क थ्रूपुट आदि दोनों के संबंध में है। आपके डेटा एक्सेस थ्रेड के समानांतर एक संगणना-गहन थ्रेड चलने से आपके डेटाबेस के प्रदर्शन में नाटकीय कमी आ सकती है।
अनुप्रयोग के विभिन्न क्षेत्रों के कारण इन डेटाबेस में विकल्पों के अलग-अलग पैलेट हैं:सर्वर-डीबी व्यापक उपयोगकर्ता और सही प्रबंधन, विचारों और संग्रहीत प्रक्रियाओं के लिए समर्थन प्रदान करता है, जबकि एम्बेडेड डेटाबेस में आमतौर पर उपयोगकर्ताओं और अधिकार प्रबंधन के लिए कोई समर्थन नहीं होता है और विचारों के लिए सीमित समर्थन होता है। और संग्रहीत कार्यविधियाँ (बाद वाले सर्वर साइड पर चलने के अपने अधिकांश लाभों को खो देते हैं)। डेटा थ्रूपुट RDBMS की एक सामान्य अड़चन है, सर्वर संस्करण आमतौर पर धारीदार RAID वॉल्यूम पर स्थापित होते हैं, जबकि एम्बेडेड DB अक्सर मेमोरी-ओरिएंटेड होते हैं (मेमोरी में सभी वास्तविक डेटा को रखने का प्रयास करें) और डेटा स्टोरेज एक्सेस ऑपरेशन को कम करते हैं।
तो, शायद यह समझ में आता है कि .Net के लिए विभिन्न एम्बेडेड RDBMS की तुलना उनके प्रदर्शन के लिए की जाए, जैसे MS SQL CE 4.0, SQLite, Firebird Embedded, TurboSQL . मैं सामान्य नॉन-पीक ऑपरेशन के दौरान भारी अंतर की उम्मीद नहीं करता, जबकि कुछ डेटाबेस OS के साथ बेहतर एकीकरण के कारण बड़े BLOB के लिए बेहतर समर्थन प्रदान कर सकते हैं।
-- अपडेट --
मुझे अपने अंतिम शब्द वापस लेने होंगे, क्योंकि मेरा त्वरित कार्यान्वयन बहुत ही रोचक परिणाम दिखाता है।
मैंने दोनों डेटा प्रदाताओं का परीक्षण करने के लिए एक छोटा कंसोल एप्लिकेशन लिखा है, यदि आप उनके साथ स्वयं प्रयोग करना चाहते हैं तो यहां आपके लिए स्रोत कोड है।
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SQLite;
using System.Data.SqlServerCe;
using System.Data.Common;
namespace TestSQL
{
class Program
{
const int NUMBER_OF_TESTS = 1000;
private static string create_table;
private static string create_table_sqlce = "CREATE TABLE Test ( id integer not null identity primary key, textdata nvarchar(500));";
private static string create_table_sqlite = "CREATE TABLE Test ( id integer not null primary key, textdata nvarchar(500));";
private static string drop_table = "DROP TABLE Test";
private static string insert_data = "INSERT INTO Test (textdata) VALUES ('{0}');";
private static string read_data = "SELECT textdata FROM Test WHERE id = {0}";
private static string update_data = "UPDATE Test SET textdata = '{1}' WHERE id = {0}";
private static string delete_data = "DELETE FROM Test WHERE id = {0}";
static Action<DbConnection> ACreateTable = (a) => CreateTable(a);
static Action<DbConnection> ATestWrite = (a) => TestWrite(a, NUMBER_OF_TESTS);
static Action<DbConnection> ATestRead = (a) => TestRead(a, NUMBER_OF_TESTS);
static Action<DbConnection> ATestUpdate = (a) => TestUpdate(a, NUMBER_OF_TESTS);
static Action<DbConnection> ATestDelete = (a) => TestDelete(a, NUMBER_OF_TESTS);
static Action<DbConnection> ADropTable = (a) => DropTable(a);
static Func<Action<DbConnection>,DbConnection, TimeSpan> MeasureExecTime = (a,b) => { var start = DateTime.Now; a(b); var finish = DateTime.Now; return finish - start; };
static Action<string, TimeSpan> AMeasureAndOutput = (a, b) => Console.WriteLine(a, b.TotalMilliseconds);
static void Main(string[] args)
{
// opening databases
SQLiteConnection.CreateFile("sqlite.db");
SQLiteConnection sqliteconnect = new SQLiteConnection("Data Source=sqlite.db");
SqlCeConnection sqlceconnect = new SqlCeConnection("Data Source=sqlce.sdf");
sqlceconnect.Open();
sqliteconnect.Open();
Console.WriteLine("=Testing CRUD performance of embedded DBs=");
Console.WriteLine(" => Samplesize: {0}", NUMBER_OF_TESTS);
create_table = create_table_sqlite;
Console.WriteLine("==Testing SQLite==");
DoMeasures(sqliteconnect);
create_table = create_table_sqlce;
Console.WriteLine("==Testing SQL CE 4.0==");
DoMeasures(sqlceconnect);
Console.ReadKey();
}
static void DoMeasures(DbConnection con)
{
AMeasureAndOutput("Creating table: {0} ms", MeasureExecTime(ACreateTable, con));
AMeasureAndOutput("Writing data: {0} ms", MeasureExecTime(ATestWrite, con));
AMeasureAndOutput("Updating data: {0} ms", MeasureExecTime(ATestUpdate, con));
AMeasureAndOutput("Reading data: {0} ms", MeasureExecTime(ATestRead, con));
AMeasureAndOutput("Deleting data: {0} ms", MeasureExecTime(ATestDelete, con));
AMeasureAndOutput("Dropping table: {0} ms", MeasureExecTime(ADropTable, con));
}
static void CreateTable(DbConnection con)
{
var sqlcmd = con.CreateCommand();
sqlcmd.CommandText = create_table;
sqlcmd.ExecuteNonQuery();
}
static void TestWrite(DbConnection con, int num)
{
for (; num-- > 0; )
{
var sqlcmd = con.CreateCommand();
sqlcmd.CommandText = string.Format(insert_data,Guid.NewGuid().ToString());
sqlcmd.ExecuteNonQuery();
}
}
static void TestRead(DbConnection con, int num)
{
Random rnd = new Random(DateTime.Now.Millisecond);
for (var max = num; max-- > 0; )
{
var sqlcmd = con.CreateCommand();
sqlcmd.CommandText = string.Format(read_data, rnd.Next(1,num-1));
sqlcmd.ExecuteNonQuery();
}
}
static void TestUpdate(DbConnection con, int num)
{
Random rnd = new Random(DateTime.Now.Millisecond);
for (var max = num; max-- > 0; )
{
var sqlcmd = con.CreateCommand();
sqlcmd.CommandText = string.Format(update_data, rnd.Next(1, num - 1), Guid.NewGuid().ToString());
sqlcmd.ExecuteNonQuery();
}
}
static void TestDelete(DbConnection con, int num)
{
Random rnd = new Random(DateTime.Now.Millisecond);
var order = Enumerable.Range(1, num).ToArray<int>();
Action<int[], int, int> swap = (arr, a, b) => { int c = arr[a]; arr[a] = arr[b]; arr[b] = c; };
// shuffling the array
for (var max=num; max-- > 0; ) swap(order, rnd.Next(0, num - 1), rnd.Next(0, num - 1));
foreach(int index in order)
{
var sqlcmd = con.CreateCommand();
sqlcmd.CommandText = string.Format(delete_data, index);
sqlcmd.ExecuteNonQuery();
}
}
static void DropTable(DbConnection con)
{
var sqlcmd = con.CreateCommand();
sqlcmd.CommandText = drop_table;
sqlcmd.ExecuteNonQuery();
}
}
}
आवश्यक अस्वीकरण:
- मुझे अपनी मशीन पर ये परिणाम मिले:डेल प्रिसिजन वर्कस्टेशन T7400 2 Intel Xeon E5420 CPU और 8GB RAM से लैस है, जो 64bit Win7 Enterprise पर चलता है ।
- मैंने दोनों DB के लिए डिफ़ॉल्ट सेटिंग का उपयोग किया है कनेक्शन स्ट्रिंग के साथ "डेटा स्रोत =डेटाबेस_फाइल_नाम"।
- मैंने SQL CE 4.0 और SQLite/System.Data.SQLite (आज, 3 जून 2011 से) दोनों के नवीनतम संस्करणों का उपयोग किया है।
यहां दो अलग-अलग नमूनों के परिणाम दिए गए हैं:
> =Testing CRUD performance of embedded DBs= > => Samplesize: 200 > ==Testing SQLite== > Creating table: 396.0396 ms > Writing data: 22189.2187 ms > Updating data: 23591.3589 ms > Reading data: 21.0021 ms > Deleting data: 20963.0961 ms > Dropping table: 85.0085 ms > ==Testing SQL CE 4.0== > Creating table: 16.0016 ms > Writing data: 25.0025 ms > Updating data: 56.0056 ms > Reading data: 28.0028 ms > Deleting data: 53.0053 ms > Dropping table: 11.0011 ms
... और एक बड़ा नमूना:
=Testing CRUD performance of embedded DBs= => Samplesize: 1000 ==Testing SQLite== Creating table: 93.0093 ms Writing data: 116632.6621 ms Updating data: 104967.4957 ms Reading data: 134.0134 ms Deleting data: 107666.7656 ms Dropping table: 83.0083 ms ==Testing SQL CE 4.0== Creating table: 16.0016 ms Writing data: 128.0128 ms Updating data: 307.0307 ms Reading data: 164.0164 ms Deleting data: 306.0306 ms Dropping table: 13.0013 ms
इसलिए, जैसा कि आप देख सकते हैं, SQLCE की तुलना में किसी भी लेखन कार्य (बनाना, अपडेट करना, हटाना) को SQLite में लगभग 1000x अधिक समय की आवश्यकता होती है। यह आवश्यक रूप से इस डेटाबेस के सामान्य खराब प्रदर्शन को नहीं दर्शाता है और निम्न के कारण हो सकता है:
- SQLite के लिए मैं जिस डेटा प्रदाता का उपयोग करता हूं वह है System.Data.SQLite , यह एक मिश्रित असेंबली है जिसमें प्रबंधित और अप्रबंधित दोनों कोड होते हैं (SQLite मूल रूप से C में पूरी तरह से लिखा गया है और DLL केवल बाइंडिंग प्रदान करता है)। संभवत:पी/इनवोक और डेटा मार्शलिंग ऑपरेशन के समय का एक अच्छा हिस्सा खा जाता है।
- सबसे अधिक संभावना है कि SQLCE 4.0 डिफ़ॉल्ट रूप से सभी डेटा को मेमोरी में कैश कर देता है, जबकि SQLite हर बार परिवर्तन होने पर अधिकांश डेटा को सीधे डिस्क स्टोरेज में फ्लश कर देता है। कनेक्शन स्ट्रिंग के माध्यम से दोनों डेटाबेस के लिए सैकड़ों पैरामीटर की आपूर्ति कर सकते हैं और उन्हें उचित रूप से ट्यून कर सकते हैं।
- मैंने डीबी का परीक्षण करने के लिए एकल प्रश्नों की एक श्रृंखला का उपयोग किया। कम से कम SQLCE विशेष .Net कक्षाओं के माध्यम से थोक संचालन का समर्थन करता है जो यहां बेहतर अनुकूल होगा। यदि SQLite भी उनका समर्थन करता है (क्षमा करें, मैं यहां विशेषज्ञ नहीं हूं और मेरी त्वरित खोज से कुछ भी आशाजनक नहीं निकला) तो उनकी तुलना करना भी अच्छा होगा।
- मैंने x64 मशीनों पर SQLite के साथ कई समस्याएं देखी हैं (उसी .net एडेप्टर का उपयोग करके):डेटा कनेक्शन के अप्रत्याशित रूप से बंद होने से लेकर डेटाबेस फ़ाइल भ्रष्टाचार तक। मुझे लगता है कि डेटा एडेप्टर या स्वयं लाइब्रेरी के साथ कुछ स्थिरता समस्याएं हैं।