MySQL

2008-09-18 5 views
57

में DATETIME फ़ील्ड के दिनांक भाग पर कोई अनुक्रमणिका कैसे बनाता है I DATETIME फ़ील्ड के दिनांक भाग पर एक अनुक्रमणिका कैसे बना सकता हूं?MySQL

mysql> SHOW COLUMNS FROM transactionlist; 
+-------------------+------------------+------+-----+---------+----------------+ 
| Field    | Type    | Null | Key | Default | Extra   | 
+-------------------+------------------+------+-----+---------+----------------+ 
| TransactionNumber | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| WagerId   | int(11)   | YES | MUL | 0  |    | 
| TranNum   | int(11)   | YES | MUL | 0  |    | 
| TranDateTime  | datetime   | NO |  | NULL |    | 
| Amount   | double   | YES |  | 0  |    | 
| Action   | smallint(6)  | YES |  | 0  |    | 
| Uid    | int(11)   | YES |  | 1  |    | 
| AuthId   | int(11)   | YES |  | 1  |    | 
+-------------------+------------------+------+-----+---------+----------------+ 
8 rows in set (0.00 sec) 

TranDateTime एक लेनदेन का दिनांक और समय बचाने के लिए के रूप में यह होता है

मेरे तालिका उस में 1,000,000 से अधिक रिकॉर्ड और बयान है

SELECT * FROM transactionlist where date(TranDateTime) = '2008-08-17' 

एक लंबा समय लगता प्रयोग किया जाता है।

संपादित करें:

"Why MySQL’s DATETIME can and should be avoided"

+3

चेतावनी टिप्पणी आप एक बार देख सुझाव दिया: पोस्ट इस तरह के एक उत्साह के साथ लिखा गया है और क्रोध है कि यह लगभग बचपना के बिंदु पर सीमाओं। और लेखक किसी भी आलोचना को हरा नहीं रहा है, जबकि अभी भी उल्लेख है कि वह जो भी कहता है उसके पीछे खड़ा है, फिर भी उसका मुद्दा प्रत्येक के साथ पतला हो रहा है। लेकिन फिर भी, यदि आप टिप्पणियां पढ़ते हैं, तो समय की बर्बादी नहीं है। – kommradHomer

उत्तर

50

यदि मुझे सही याद है, तो यह एक संपूर्ण तालिका स्कैन चलाएगा क्योंकि आप एक फ़ंक्शन के माध्यम से कॉलम पास कर रहे हैं। MySQL आज्ञाकारिता से प्रत्येक कॉलम के लिए फ़ंक्शन चलाएगा, इंडेक्स को छोड़कर क्वेरी ऑप्टिमाइज़र वास्तव में फ़ंक्शन के परिणाम नहीं जान सकता है।

SELECT * FROM transactionlist 
WHERE TranDateTime BETWEEN '2008-08-17 00:00:00' AND '2008-08-18 23:59:59'; 

कि तुम सब कुछ है कि 2008-08-17 पर हुआ है, और सब कुछ है कि वास्तव में 2008-08-18 00:00:00 पर हुआ देना चाहिए:

मुझे क्या होगा की तरह कुछ है। यदि यह एक समस्या है, तो आप दूसरे शब्द को '2008-08-17 23:59:59' में बदल सकते हैं और बस 2008-08-17 प्राप्त कर सकते हैं।

+0

वास्तव में बहुत प्रभावी है कि ... – Arfeen

+1

मैं के रूप में सिर्फ 'YYYY-MM-DD 00:00:00' – kommradHomer

+3

मैं जानता हूँ कि यह एक पुरानी जवाब है के लिए एक शॉर्टकट के लिए इस प्रयोग के बारे में सोच करने के लिए इस्तेमाल, लेकिन मैं करने के लिए मजबूर महसूस इंगित करें कि MySQL 'DATETIME' के लिए स्ट्रिंग तुलना का उपयोग करता है; आपकी क्वेरी सही परिणाम देती है और इसमें 'TranDateTime = 2008-08-18 00: 00: 00' वाली पंक्तियां शामिल नहीं होती हैं। – Arth

0

क्या समझाना 'करता है कहते हैं पर इस ब्लॉग पोस्ट पर एक नज़र है? (Transactionlist से व्याख्या चुनें * चलाने जहां तिथि (TranDateTime) = '2008-08-17')

यह तिथि() फ़ंक्शन की वजह से अपने सूचकांक का उपयोग नहीं कर रहा है, तो एक सीमा क्वेरी तेजी से चलाना चाहिए:

चुनें * लेनदेन सूची से जहां TranDateTime> = '2008-08-17' और TranDateTime < '2008-08-18'

+1

यदि आप दिनांक() का उपयोग करते हैं तो आप इंडेक्स को नहीं दबाएंगे। MySQL इस तरह की फ़ंक्शन कॉल के अंदर इंडेक्स का उपयोग नहीं कर सकता है। – JBB

3

मुझे mySql के विनिर्देशों के बारे में पता नहीं है, लेकिन दिनांक फ़ील्ड को अनुक्रमणित करने में क्या नुकसान है अपनी पूर्णता में?

तो बस खोज:

select * from translist 
    where TranDateTime > '2008-08-16 23:59:59' 
     and TranDateTime < '2008-08-18 00:00:00' 

अनुक्रमित बी पेड़ या कुछ और कि उचित, इन जल्दी से पाया जाना चाहिए है कर रहे हैं।

9

मुझे प्यारा लगने का मतलब नहीं है, लेकिन एक नया तरीका एक नया कॉलम जोड़ना होगा जिसमें उसमें केवल तारीख भाग और अनुक्रमणिका शामिल हो।

+0

यूप - और केवल समय के साथ एक कॉलम जोड़ें, और DATETIME को पूरी तरह खत्म करें। – JBB

+0

मेरे वर्तमान समाधान एक और क्षेत्र कॉल 'तारीख' जोड़ सकते हैं और जब मैं TranDateTime अद्यतन तिथि भी अद्यतन किया जाता है। अब मेरे पास 'डेट' पर एक इंडेक्स है और क्वेरी बहुत तेज है मेरी तालिका द्वारा आकार में +5% –

0

किसी फ़ंक्शन के आधार पर इंडेक्स बनाने की बजाय (यदि यह MySQL में भी संभव है) तो अपना क्लॉज रेंज तुलना करें। कुछ की तरह:

कहाँ TranDateTime> '2008-08-17 00:00:00' और TranDateTime < '2008-08-17 11:59:59')

यह सुविधा देता है चयन करने के लिए डीबी TranDateTime पर सूचकांक का उपयोग करता है (एक है, है ना?)।

2

माईएसक्यूएल साइट पर इस मुद्दे के लिए फीचर अनुरोध पर वैलेरी क्रावचुक ने इस विधि का उपयोग करने के लिए कहा।

"इस बीच आप DATETIME मानों को स्ट्रिंग के रूप में संग्रहीत करने के लिए वर्ण कॉलम का उपयोग कर सकते हैं, केवल पहले एन वर्णों को अनुक्रमित किया जा रहा है। MySQL 5 में ट्रिगर्स के कुछ सावधानीपूर्वक उपयोग के साथ आप इस विचार के आधार पर एक उचित मजबूत समाधान बना सकते हैं।"

आप इस कॉलम को जोड़ने के लिए नियमित रूप से बहुत आसान लिख सकते हैं, और फिर ट्रिगर्स के साथ इस कॉलम को सिंक किया जाता है। इस स्ट्रिंग कॉलम पर सूचकांक बहुत तेज़ होना चाहिए।

8

आप केवल तारीख भाग पर एक अनुक्रमणिका नहीं बना सकते हैं। क्या आपके पास कोई कारण है?

भले ही आप केवल तारीख के भाग पर एक इंडेक्स बना सकें, तो ऑप्टिमाइज़र शायद उपरोक्त क्वेरी के लिए इसका उपयोग नहीं करेगा।

मुझे लगता है कि आप पाएंगे कि

SELECT * FROM transactionlist WHERE TranDateTime BETWEEN '2008-08-17' AND '2008-08-18' 

कुशल है और आप क्या चाहते हैं नहीं करता है।

0

मुझे mySQL के विनिर्देशों के बारे में पता नहीं है, लेकिन पूरी तरह से तिथि फ़ील्ड को अनुक्रमणित करने में क्या नुकसान है?

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

जोड़ने के लिए कुछ भी नहीं है।

शायद तुम अभिकलन (गणना की?) अनुक्रमित की तरह कुछ मतलब ... लेकिन आज तक, मैं केवल Intersystems कैश में यह देखा है। मुझे नहीं लगता कि संबंधपरक डेटाबेस (AFAIK) में एक मामला है।

एक अच्छा समाधान, मेरी राय में, निम्नलिखित (अद्यतन clintp उदाहरण) है:

SELECT * FROM translist 
WHERE TranDateTime >= '2008-08-17 00:00:00.0000' 
    AND TranDateTime < '2008-08-18 00:00:00.0000' 

आप का उपयोग करें 00:00:00.0000 या 00:00 मेरी राय में कोई फर्क नहीं पड़ता (मैं आम तौर पर इस प्रारूप में यह उपयोग किया है)।

0

सिर्फ दिनांकों convert(datetime, left(date_field,10)) और उसके बाद सूचकांक कि के साथ एक नया क्षेत्रों बनाएँ।

1

एक अच्छा और अच्छा समाधान जो कि बहुत अच्छा काम कर रहा है, टाइमटाम्प का उपयोग समय के बजाय समय के रूप में करना है। इसे आईएनटी के रूप में संग्रहीत किया जाता है और पर्याप्त रूप से अनुक्रमित किया जा रहा है। व्यक्तिगत रूप से मुझे लेनदेन तालिका पर ऐसी समस्या का सामना करना पड़ा, जिसमें लगभग दस लाख रिकॉर्ड हैं और कठोर धीमे हो गए हैं, अंत में मैंने इंगित किया कि यह खराब अनुक्रमित फ़ील्ड (डेटाटाइम) के कारण होता है। अब यह बहुत तेज़ चलता है।

-2

किसी ने भी LIKE का उपयोग करने का सुझाव क्यों नहीं दिया? क्या वह नौकरी भी नहीं करता है? क्या यह जितना तेज होगा?

SELECT * FROM transactionlist where TranDateTime LIKE '2008-08-17%' 
1

डेटाटाइम कुछ% इंडेक्स को पकड़ नहीं पाएगा।

इसका उपयोग करें: जहां datetime_field> = curdate();
कि सूचकांक पकड़ेगा,
और कवर आज: 00: 00: 00 आज से ऊपर: 23: 59: 59
हो गया।

5

एक और विकल्प (7.5.3 और ऊपर के लिए प्रासंगिक) डेटाटाइम कॉलम के आधार पर जेनरेट/वर्चुअल कॉलम बनाना है, फिर इसे इंडेक्स करें। लिंक के लिए

CREATE TABLE `table` (
`my_datetime` datetime NOT NULL, 
`my_date` varchar(12) GENERATED ALWAYS AS (DATE(`my_daetime`)) STORED, 
KEY `my_idx` (`my_date`) 
) ENGINE=InnoDB; 
+0

आकार में वृद्धि क्यों आभासी है और वर्चुअल नहीं है? – 0x13a

+0

यदि आप इंडेक्स करना चाहते हैं तो इसे संग्रहीत किया जाना चाहिए .. इंडेक्स के बिना यह वर्चुअल –

+0

thx हो सकता है, मैंने कल्पना की, मैं इस आलेख के साथ भ्रमित हो गया https://www.percona.com/blog/2016/03/04/virtual -columns-in-mysql-and-mariadb/ – 0x13a

 संबंधित मुद्दे