केवल मेमोरी में PostgreSQL चलाना


104

मैं एक छोटा PostgreSQL डेटाबेस चलाना चाहता हूं जो केवल मेमोरी में चलता है, प्रत्येक यूनिट टेस्ट के लिए जो मैं लिखता हूं। उदाहरण के लिए:

@Before
void setUp() {
    String port = runPostgresOnRandomPort();
    connectTo("postgres://localhost:"+port+"/in_memory_db");
    // ...
}

आदर्श रूप से मेरे पास एक एकल पोस्टग्रैग्‍ट एग्‍जेक्‍टेबल है जिसे वर्जन कंट्रोल में चेक किया गया है, जो यूनिट टेस्‍ट का उपयोग करेगा।

कुछ पसंद है HSQL, लेकिन पोस्टग्रेज के लिए। मैं उसे कैसे कर सकता हूँ?

क्या मुझे ऐसा पोस्टग्रेज संस्करण मिल सकता है? मैं इसे डिस्क का उपयोग न करने का निर्देश कैसे दे सकता हूं?

जवाबों:


49

Postgres के साथ यह संभव नहीं है। यह HSQLDB या MySQL जैसे इन-प्रोसेस / इन-मेमोरी इंजन की पेशकश नहीं करता है।

यदि आप एक स्व-सम्‍मिलित वातावरण बनाना चाहते हैं तो आप Postgres बायनेरिज़ को SVN में डाल सकते हैं (लेकिन यह केवल एकल निष्पादन से अधिक है)।

इससे पहले कि आप कुछ भी कर सकें, आपको अपने परीक्षण डेटाबेस को सेट करने के लिए initdb चलाने की आवश्यकता होगी । यह एक बैच फ़ाइल से या Runtime.exec () का उपयोग करके किया जा सकता है। लेकिन ध्यान दें कि initdb कुछ ऐसा नहीं है जो तेज़ हो। आप निश्चित रूप से प्रत्येक परीक्षा के लिए उसे नहीं चलाना चाहेंगे। हालांकि आप अपने टेस्ट-सूट से पहले इसे चलाना छोड़ सकते हैं।

हालांकि जब यह किया जा सकता है, तो मैं आपके परीक्षण को चलाने से पहले एक समर्पित पोस्टग्रेज इंस्टॉलेशन करने की सलाह दूंगा जहां आप बस अपने टेस्ट डेटाबेस को फिर से बनाते हैं।

आप टेम्प्लेट डेटाबेस का उपयोग करके परीक्षण-डेटाबेस को फिर से बना सकते हैं, जो इसे काफी तेज बनाता है ( प्रत्येक परीक्षण चलाने के लिए initdb चलाने की तुलना में बहुत तेज)


8
ऐसा लगता है कि इरविन द्वारा नीचे दिए गए दूसरे उत्तर को सही उत्तर के रूप में चिह्नित किया जाना चाहिए
vfclists

3
@vfclists वास्तव में, एक रैमडिस्क पर एक टेबलस्पेस वास्तव में एक बुरा विचार है। ऐसा मत करो। देखें postgresql.org/docs/devel/static/manage-ag-tablespaces.html , stackoverflow.com/q/9407442/398670
क्रेग रिंगर

1
@ क्रेगिंगर: इस विशेष प्रश्न के लिए स्पष्ट करने के लिए: मूल्यवान डेटा (और चेतावनी के लिए धन्यवाद) के साथ मिश्रण करना एक बुरा विचार है। एक समर्पित डीबी क्लस्टर के साथ यूनिट-परीक्षण के लिए, एक रैमडिस्क ठीक है।
एरविन ब्रान्डसेट्टर

1
डॉकटर-उपयोग सामान्य होने के साथ, कुछ लोग एक उपकरण के साथ सफल रहे हैं testcontainers, जो अनिवार्य रूप से आपके परीक्षण स्टार्टअप को एक थकावट, डॉकटराइज़्ड, पोस्टग्रेज-इंस्टेंस देता है। देखें github.com/testcontainers/testcontainers-java/blob/master/…
हंस वेस्टरबेक

1
@ekcrisp। यह Postgres का सही एम्बेडेड संस्करण नहीं है। पोस्टग्रेज इंस्टेंस (एक अलग प्रक्रिया में) को आसान बनाना केवल एक रैपर लाइब्रेरी है। Postgres अभी भी जावा एप्लिकेशन के "बाहर" चलेंगे और उसी प्रक्रिया में "एम्बेडेड" नहीं होंगे जो JVM
a_horse_with_no_name

77

( इन-मेमोरी पोस्टग्रेक्यूएल का उपयोग करने और इसे सामान्य करने से मेरा जवाब हिलाना ):

आप Pg इन-प्रोसेस, इन-मेमोरी नहीं चला सकते

मैं यह नहीं पता लगा सकता कि परीक्षण के लिए इन-मेमोरी पोस्टग्रेज डेटाबेस को कैसे चलाया जाए। क्या यह संभव है?

नहीं, यह संभव नहीं है। PostgreSQL C में लागू किया गया है और प्लेटफ़ॉर्म कोड पर संकलित किया गया है। H2 या डर्बी के विपरीत आप बस लोड नहीं कर सकते हैं jarऔर इसे एक भड़काऊ इन-मेमोरी DB के रूप में आग लगा सकते हैं।

SQLite के विपरीत, जिसे C में भी लिखा गया है और प्लेटफ़ॉर्म कोड में संकलित किया गया है, PostgreSQL को प्रक्रिया में लोड नहीं किया जा सकता है। इसके लिए कई प्रक्रियाओं (एक प्रति कनेक्शन) की आवश्यकता होती है क्योंकि यह एक बहु-आयामी है, न कि एक मल्टीथ्रेडिंग, आर्किटेक्चर। मल्टीप्रोसेसिंग आवश्यकता का मतलब है कि आपको पोस्टमास्टर को एक स्टैंडअलोन प्रक्रिया के रूप में लॉन्च करना होगा

इसके बजाय: एक कनेक्शन पूर्व-कॉन्फ़िगर करें

मेरा सुझाव है कि काम करने के लिए किसी विशेष होस्टनाम / उपयोगकर्ता नाम / पासवर्ड की अपेक्षा करने के लिए बस अपने परीक्षण लिखना और परीक्षण CREATE DATABASEएक फेंकने योग्य डेटाबेस का उपयोग करना, फिर DROP DATABASEरन के अंत में। प्रॉपर्टी फ़ाइल से डेटाबेस कनेक्शन विवरण प्राप्त करें, लक्ष्य गुण, पर्यावरण चर आदि का निर्माण करें।

किसी मौजूदा PostgreSQL उदाहरण का उपयोग करना आपके लिए पहले से सुरक्षित डेटाबेस है, इसलिए जब तक आप अपने यूनिट परीक्षणों की आपूर्ति करने वाले उपयोगकर्ता के लिए सुपरसुअर नहीं है, केवल CREATEDBअधिकारों वाला उपयोगकर्ता है। सबसे कम आप अन्य डेटाबेस में प्रदर्शन समस्याएँ पैदा करेंगे। मैं उस कारण के परीक्षण के लिए एक पूरी तरह से पृथक PostgreSQL इंस्टॉल करना पसंद करता हूं।

इसके बजाय: परीक्षण के लिए एक भगोड़ा PostgreSQL उदाहरण लॉन्च करें

वैकल्पिक रूप से, यदि आप वास्तव में उत्सुक हैं तो आप अपने परीक्षण का उपयोगinitdbpostgresinitdbpg_hba.conftrustpostgres कर सकते हैं और बायनेरिज़ का पता लगा सकते हैं , डेटाबेस बनाने के लिए दौड़ सकते हैं, संशोधित कर सकते हैं , इसे यादृच्छिक पोर्ट पर शुरू कर सकते हैं, उपयोगकर्ता बना सकते हैं, डीबी बना सकते हैं और परीक्षण चला सकते हैं । तुम भी एक जार में कई आर्किटेक्चर के लिए PostgreSQL बायनेरिज़ को बंडल कर सकते हैं और परीक्षणों को चलाने से पहले एक अस्थायी निर्देशिका के लिए वर्तमान आर्किटेक्चर के लिए अनपैक कर सकते हैं।

व्यक्तिगत रूप से मुझे लगता है कि एक बड़ी पीड़ा है जिसे टाला जाना चाहिए; यह आसान है बस एक परीक्षण DB कॉन्फ़िगर किया गया है। हालांकि, इसमें include_dirसमर्थन के आगमन के साथ थोड़ा आसान हो गया है postgresql.conf; अब आप केवल एक पंक्ति को जोड़ सकते हैं, फिर बाकी सभी के लिए एक उत्पन्न विन्यास फाइल लिख सकते हैं।

PostgreSQL के साथ तेज़ परीक्षण

परीक्षण उद्देश्यों के लिए PostgreSQL के प्रदर्शन को सुरक्षित रूप से कैसे बेहतर बनाया जाए, इसके बारे में अधिक जानकारी के लिए, मैंने पहले इस विषय पर लिखा एक विस्तृत जवाब देखें: तेजी से परीक्षण के लिए PostgreSQL का अनुकूलन करें

H2 की PostgreSQL बोली एक सही विकल्प नहीं है

इसके बजाय कुछ लोग परीक्षण चलाने के लिए PostgreSQL बोली मोड में H2 डेटाबेस का उपयोग करते हैं। मुझे लगता है कि उत्पादन तैनाती के लिए परीक्षण और PostgreSQL के लिए SQLite का उपयोग करने वाले रेल के रूप में लगभग उतना ही बुरा है।

H2 कुछ PostgreSQL एक्सटेंशन का समर्थन करता है और PostgreSQL बोली का अनुकरण करता है। हालांकि, यह सिर्फ एक अनुकरण है। आपको ऐसे क्षेत्र मिलेंगे जहां H2 एक क्वेरी स्वीकार करता है लेकिन PostgreSQL नहीं करता है, जहां व्यवहार भिन्न होता है, आदि । आपको बहुत सारे स्थान मिलेंगे जहाँ PostgreSQL कुछ ऐसा करने का समर्थन करता है जो लिखने के समय H2 बस नहीं कर सकता है - जैसे विंडो फ़ंक्शंस।

यदि आप इस दृष्टिकोण की सीमाओं को समझते हैं और आपके डेटाबेस की पहुंच सरल है, तो H2 ठीक हो सकता है। लेकिन उस मामले में आप शायद ORM के लिए एक बेहतर उम्मीदवार हैं जो डेटाबेस को सार करता है क्योंकि आप वैसे भी इसकी दिलचस्प विशेषताओं का उपयोग नहीं कर रहे हैं - और उस स्थिति में, आपको डेटाबेस संगतता के बारे में अधिक ध्यान रखने की आवश्यकता नहीं है।

Tablespaces का जवाब नहीं!

है एक "में स्मृति" डेटाबेस बनाने के लिए एक टेबल-स्पेस का उपयोग करें। न केवल यह अनावश्यक है, क्योंकि यह प्रदर्शन को काफी मदद नहीं करेगा, बल्कि यह किसी भी अन्य के लिए उपयोग को बाधित करने का एक शानदार तरीका है जिसे आप उसी पोस्टग्रेक्यूएल इंस्टॉल में देख सकते हैं। 9.4 प्रलेखन में अब निम्नलिखित चेतावनी शामिल है :

चेतावनी

भले ही मुख्य PostgreSQL डेटा निर्देशिका के बाहर स्थित है, टेबलस्पेस डेटाबेस क्लस्टर का एक अभिन्न अंग हैं और डेटा फ़ाइलों के स्वायत्त संग्रह के रूप में नहीं माना जा सकता है। वे मुख्य डेटा निर्देशिका में निहित मेटाडेटा पर निर्भर हैं, और इसलिए एक अलग डेटाबेस क्लस्टर से जुड़ा नहीं जा सकता है या व्यक्तिगत रूप से समर्थित नहीं हो सकता है। इसी तरह, यदि आप एक टेबलस्पेस (फ़ाइल विलोपन, डिस्क विफलता, आदि) खो देते हैं, तो डेटाबेस क्लस्टर अपठनीय या प्रारंभ करने में असमर्थ हो सकता है। अस्थायी फ़ाइल सिस्टम पर एक टेम्पेस्पेस रखने की तरह एक रैमडिस्क पूरे क्लस्टर की विश्वसनीयता को जोखिम में डालता है।

क्योंकि मैंने देखा कि बहुत से लोग ऐसा कर रहे थे और मुसीबत में चल रहे थे।

(यदि आपने ऐसा कर लिया है तो आप mkdirफिर से शुरू करने के लिए PostgreSQL प्राप्त करने के लिए लापता टेबलस्पेस निर्देशिका कर सकते हैं , फिर DROPलापता डेटाबेस, टेबल आदि। यह सिर्फ ऐसा नहीं करना बेहतर है।)


1
मैं यहां दी गई चेतावनी के बारे में स्पष्ट नहीं हूं। अगर मैं यूनिट टेस्ट तेजी से चलाने की कोशिश कर रहा हूं, तो इसमें क्लस्टर क्यों शामिल है? क्या यह सब मेरे पीजी के स्थानीय, फेंकने वाले उदाहरण पर नहीं होना चाहिए? यदि क्लस्टर (एक का) दूषित है तो वह बात क्यों करता है, मैं इसे वैसे भी हटाने की योजना बना रहा था।
गेट्स वीपी

1
@GatesVP PostgreSQL "क्लस्टर" शब्द का उपयोग कुछ अजीब तरीके से करता है, PostgreSQL उदाहरण (डेटा निर्देशिका, डेटाबेस, पोस्टमास्टर, आदि का संग्रह) को संदर्भित करने के लिए। तो यह "कंप्यूट क्लस्टर" के अर्थ में "क्लस्टर" नहीं है। हां, यह कष्टप्रद है, और मैं उस शब्दावली को बदलना चाहता हूं। और अगर यह तो निश्चित रूप से यह बात नहीं है throwaway है, लेकिन लोगों को नियमित रूप से एक throwaway में-स्मृति करने का प्रयास टेबल-स्पेस स्थापित एक PostgreSQL पर है कि डेटा वे अन्यथा के बारे में परवाह शामिल हैं। ये एक समस्या है।
क्रेग रिंगर

ठीक है, यह दोनों "मैंने क्या सोचा" और "बहुत डरावना" है , रैमड्राइव समाधान स्पष्ट रूप से केवल एक स्थानीय डीबी पर है जिसमें कोई उपयोगी डेटा नहीं है। लेकिन कोई भी एक मशीन के खिलाफ इकाई परीक्षण क्यों चलाना चाहेगा जो स्वयं की मशीन नहीं है? आपके जवाब के आधार पर, Tablespaces + RamDisk पूरी तरह से आपके स्थानीय मशीन पर चलने वाले PGSQL के एक वास्तविक यूनिट टेस्ट उदाहरण के लिए पूरी तरह से वैध लगता है।
गेट्स वीपी

1
@ गेट्सवीपी कुछ लोग अपनी स्थानीय मशीन पर उन चीजों को ध्यान में रखते हैं जो ठीक है - जो ठीक है, लेकिन फिर उसी डीबी स्थापित के खिलाफ इकाई परीक्षण चलाने के लिए थोड़ा मूर्खतापूर्ण है। लोग मूर्ख हैं, यद्यपि। उनमें से कुछ भी उचित बैकअप नहीं रखते हैं। पालता है।
क्रेग रिंगर

किसी भी स्थिति में, यदि आप रैमडिस्क विकल्प पर जाने वाले हैं, तो आप वास्तव में रैम पर भी चलना चाहते हैं, इसलिए आप initdbएक नया Pg स्थापित कर सकते हैं। लेकिन वास्तव में, कम से कम लिनक्स पर एक रैमडिस्क पर चलने की तुलना में सामान्य भंडारण (fsync = बंद और अन्य डेटा स्थायित्व / सुरक्षा सुविधाओं को बंद कर दिया गया) पर तेजी से परीक्षण के लिए उपयोग किए जाने वाले Pg के बीच थोड़ा अंतर है।
क्रेग रिंगर

66

या आप एक ramfs / tempfs में एक TABLESPACE बना सकते हैं और वहाँ अपनी सभी वस्तुएँ बना सकते हैं।
मुझे हाल ही में लिनक्स पर वास्तव में ऐसा करने के बारे में एक लेख में बताया गया था ।

चेतावनी

यह आपके पूरे डेटाबेस क्लस्टर की अखंडता को खतरे में डाल सकता है ।
मैनुअल में जोड़ा चेतावनी पढ़ें।
तो यह केवल खर्च करने योग्य डेटा के लिए एक विकल्प है।

के लिए इकाई परीक्षण यह ठीक काम करना चाहिए। यदि आप एक ही मशीन पर अन्य डेटाबेस चला रहे हैं, तो सुरक्षित होने के लिए एक अलग डेटाबेस क्लस्टर (जिसका अपना पोर्ट है) का उपयोग करना सुनिश्चित करें।


4
मुझे वास्तव में लगता है कि यह बुरी सलाह है। यह मत करो। इसके बजाय, initdbएक नया उदाहरण एक tempfs या ramdisk में दिया जाता है। है एक tempfs आदि में एक टेबल-स्पेस का उपयोग करें, यह कमजोर और व्यर्थ है। आप सामान्य टेबलस्पेस का उपयोग करने और UNLOGGEDटेबल बनाने से बेहतर हैं - यह समान प्रदर्शन करेगा। और जब तक आप पूरे डीबी की अखंडता को जोखिम में नहीं डालेंगे, तब तक यह वाल परफॉर्मेंस और fsync कारकों को संबोधित नहीं करेगा (देखें stackoverflow.com/q/9407442/398670 )। यह मत करो।
क्रेग रिंगर

29

अब OpenTable से एंबेडेड PostgreSQL घटक के माध्यम से अपने JUnit परीक्षणों में PostgreSQL का इन-मेमोरी इंस्टेंस चलाना संभव है: https://github.com/opentable/otj-pg-embedded

ओटीजी-पीजी-एम्बेडेड लाइब्रेरी ( https://mvnrepository.com/artifact/com.opentable.compenders/otj-pg-embedded ) पर निर्भरता जोड़कर आप अपने @Before और में PostgreSQL के अपने स्वयं के उदाहरण को शुरू और बंद कर सकते हैं @ देखें हुक:

EmbeddedPostgres pg = EmbeddedPostgres.start();

वे JUnit को स्वचालित रूप से आपके लिए अपना PostgreSQL डेटाबेस सर्वर शुरू करने और रोकने के लिए एक JUnit नियम भी प्रदान करते हैं:

@Rule
public SingleInstancePostgresRule pg = EmbeddedPostgresRules.singleInstance();

1
छह महीने बाद इस पैकेज के साथ आपका अनुभव कैसा है? अच्छी तरह से काम करता है, या कीड़े से भरा हुआ है?
ऑलिगॉफ्रेन

@ रुम्स क्या आपने JUnit5 में प्रवास किया? कैसे आप के प्रतिस्थापन प्रयोग करते हैं @Ruleसाथ @ExtendWith? बस का उपयोग .start()में @BeforeAll?
फ्रेंकी ड्रेक

मैंने JUnit5 में माइग्रेट नहीं किया है, इसलिए मैं अभी तक आपके प्रश्न का उत्तर नहीं दे सकता हूं। माफ़ करना।
19

इसने अच्छा काम किया। धन्यवाद। अपने वसंत विन्यास में डेटा स्रोत बनाने के लिए निम्नलिखित का उपयोग करें यदि आप चाहें:DataSource embeddedPostgresDS = EmbeddedPostgres.builder().start().getPostgresDatabase();
सैकी सैन

12

परीक्षण के लिए आप एक PosgreSQL docker कंटेनर को स्पिन करने के लिए TestContainers का उपयोग कर सकते हैं : http://testcontainers.viewdocs.io/testcontainers-java/usage/database_containers/

TestContainers एक JUnit @ नियम / @ ClassRule प्रदान करते हैं : यह मोड आपके परीक्षणों से पहले एक कंटेनर के अंदर एक डेटाबेस शुरू करता है और बाद में इसे फाड़ देता है

उदाहरण:

public class SimplePostgreSQLTest {

    @Rule
    public PostgreSQLContainer postgres = new PostgreSQLContainer();

    @Test
    public void testSimple() throws SQLException {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setJdbcUrl(postgres.getJdbcUrl());
        hikariConfig.setUsername(postgres.getUsername());
        hikariConfig.setPassword(postgres.getPassword());

        HikariDataSource ds = new HikariDataSource(hikariConfig);
        Statement statement = ds.getConnection().createStatement();
        statement.execute("SELECT 1");
        ResultSet resultSet = statement.getResultSet();

        resultSet.next();
        int resultSetInt = resultSet.getInt(1);
        assertEquals("A basic SELECT query succeeds", 1, resultSetInt);
    }
}

7

अब Yandex नाम की रूसी खोज कंपनी से PostgreSQL का इन-मेमोरी संस्करण है: https://github.com/yandex-qatools/postgresql-embedded

यह फ्लैपडूड ओएसएस की एम्बेड प्रक्रिया पर आधारित है।

उपयोग करने का उदाहरण (जीथब पृष्ठ से):

// starting Postgres
final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6);
// predefined data directory
// final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6, "/path/to/predefined/data/directory");
final String url = postgres.start("localhost", 5432, "dbName", "userName", "password");

// connecting to a running Postgres and feeding up the database
final Connection conn = DriverManager.getConnection(url);
conn.createStatement().execute("CREATE TABLE films (code char(5));");

मैं इसे कुछ समय का उपयोग कर रहा हूँ। यह अच्छा काम करता है।

अद्यतन : इस परियोजना को अब सक्रिय रूप से बनाए नहीं रखा जा रहा है

Please be adviced that the main maintainer of this project has successfuly 
migrated to the use of Test Containers project. This is the best possible 
alternative nowadays.

1
यदि आप कई थ्रेड्स का उपयोग करते हैं, तो सभी प्रकार के नए और रोमांचक तरीकों से विस्फोट होना चाहिए, एक JVM या मोनो रनटाइम एम्बेड करें, अपने खुद के बच्चे की प्रक्रियाओं, या इस तरह से कुछ भी। संपादित करें : यह वास्तव में एम्बेडेड नहीं है, यह सिर्फ एक आवरण है।
क्रेग रिंगर

3

आप इन-मेमरी डेटाबेस का सहारा लिए बिना प्रदर्शन को प्राप्त करने के लिए PostgreSQL कॉन्फ़िगरेशन सेटिंग्स (जैसे कि प्रश्न में विस्तृत और यहाँ स्वीकृत उत्तर ) का भी उपयोग कर सकते हैं ।


ओपी का मुख्य मुद्दा प्रदर्शन के लिए नहीं, बल्कि एक देव और सीआई वातावरण में बूटस्ट्रैपिंग यूनिट परीक्षणों में सादगी के लिए पोस्टग्रेज का उदाहरण है।
triple.vee

0

यदि आप NodeJS का उपयोग कर रहे हैं, तो आप पोस्टग्रैब्स db की सबसे सामान्य विशेषताओं का अनुकरण करने के लिए pg- मेम (अस्वीकरण: मैं लेखक हूं) का उपयोग कर सकता हूं।

आपके पास पूर्ण-इन-मेमोरी, पृथक, प्लेटफ़ॉर्म-अज्ञेय डेटाबेस पीजी व्यवहार की नकल करेगा (यह ब्राउज़र में भी चलता है )।

मैं इसे कैसे उपयोग करने के लिए अपने इकाई परीक्षण को दिखाने के लिए एक लेख लिखा था यहां

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.